From 005620151f9d4bb33f1553ab94cd661b28a00820 Mon Sep 17 00:00:00 2001 From: Railag Date: Fri, 4 Jan 2019 16:48:43 +0300 Subject: [PATCH 1/8] Release merge (#479) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * 1.0.31 Release * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Release (#435) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Merge (#436) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release 1.1.0 [skip ci] * Update package.json * Release 1.1.0 [skip ci] * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * 1.0.31 Release (#448) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Release (#435) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Merge (#436) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release 1.1.0 [skip ci] * Update package.json * Release 1.1.0 [skip ci] * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * Release merge (#449) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Release (#435) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Merge (#436) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release 1.1.0 [skip ci] * Update package.json * Release 1.1.0 [skip ci] * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * 1.0.31 Release (#448) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Release (#435) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Merge (#436) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release 1.1.0 [skip ci] * Update package.json * Release 1.1.0 [skip ci] * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * Epankou/bug network containers not removed ewc 424 (#450) * EWC-418 added registry email validation * EWC-421 strace feature bug * EWC-421 strace feature bug fix * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * bug(fix) microservice removal: port mapping removal (EWC-424) * bug(fix) microservice removal: switched to const (EWC-424) * test(core) unit tests for agent service progress (EWC-383) (#452) * fix(cli): fix bug with generating access token for user in cli (#453) Closes EWC-443 * fix(cli): fix bug with generating access token for user in cli (EWC-453) * test(core) unit tests for agent-service (EWC-383) (#455) * bug(fix) fixed deprecated warning about Buffer constructor (EWC-422) * test(core) unit tests for catalog service (EWC-383) (#458) * Maksimchepelev/bugs (#457) * fix(cli): fix validation on delete connector Closes EWC-447 * fix(cli): fix data types and descriptions in help '... settings JSON file' -> 'Path to ... settings JSON file' flowId and catalogId type 'string' -> 'number' in help Closes EWC-445 EWC-446 * Maksimchepelev/bugs (#459) * fix(iofog): add validation for version command compare version command with isReadyToUpgrade and isReadyToRollback fields Closes EWC-448 * fix(code): fix logger is not defined error in app-helper Closes EWC-397 * test(core) unit tests for change-tracking service (EWC-383) (#460) * version 1.0.32 (#461) * Release 1.0.32 (#462) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * 1.0.31 Release (#448) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Release (#435) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Merge (#436) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release 1.1.0 [skip ci] * Update package.json * Release 1.1.0 [skip ci] * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * Epankou/bug network containers not removed ewc 424 (#450) * EWC-418 added registry email validation * EWC-421 strace feature bug * EWC-421 strace feature bug fix * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * bug(fix) microservice removal: port mapping removal (EWC-424) * bug(fix) microservice removal: switched to const (EWC-424) * test(core) unit tests for agent service progress (EWC-383) (#452) * fix(cli): fix bug with generating access token for user in cli (#453) Closes EWC-443 * test(core) unit tests for agent-service (EWC-383) (#455) * bug(fix) fixed deprecated warning about Buffer constructor (EWC-422) * test(core) unit tests for catalog service (EWC-383) (#458) * Maksimchepelev/bugs (#457) * fix(cli): fix validation on delete connector Closes EWC-447 * fix(cli): fix data types and descriptions in help '... settings JSON file' -> 'Path to ... settings JSON file' flowId and catalogId type 'string' -> 'number' in help Closes EWC-445 EWC-446 * Maksimchepelev/bugs (#459) * fix(iofog): add validation for version command compare version command with isReadyToUpgrade and isReadyToRollback fields Closes EWC-448 * fix(code): fix logger is not defined error in app-helper Closes EWC-397 * test(core) unit tests for change-tracking service (EWC-383) (#460) * version 1.0.32 (#461) * fix(iofog): add validation for version command (#463) * fix(iofog): add validation for version command compare version command with isReadyToUpgrade and isReadyToRollback fields Closes EWC-448 * fix(cli): fix data types and descriptions in help '... settings JSON file' -> 'Path to ... settings JSON file' flowId and catalogId type 'string' -> 'number' in help Closes EWC-445 EWC-446 * test(core) unit tests for connector & controller services (EWC-383) (#464) * test(core) unit tests for diagnostic service (EWC-383) (#465) * Epankou/bug route removal ewc 374 (#466) * EWC-418 added registry email validation * EWC-421 strace feature bug * EWC-421 strace feature bug fix * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * bug(fix) microservice removal: port mapping removal (EWC-424) * bug(fix) microservice removal: switched to const (EWC-424) * bug(fix) routes removal: added routes update on connector update (EWC-374) * bug(fix) routes removal: added routes update on connector update (EWC-374) * bug(fix) tests (EWC-374) * bug(fix) create connectorPortService (EWC-374) * bug(fix) tests (EWC-374) * bug(fix) refactoring (EWC-374) * test(core) unit tests for email activation service (EWC-383) (#468) * test(core) unit tests for flow service (EWC-383) (#469) * test(core) unit tests for iofog service (EWC-383) (#470) * Epankou/bug hal usb cli ewc 449 (#471) * EWC-418 added registry email validation * EWC-421 strace feature bug * EWC-421 strace feature bug fix * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * bug(fix) microservice removal: port mapping removal (EWC-424) * bug(fix) microservice removal: switched to const (EWC-424) * bug(fix) routes removal: added routes update on connector update (EWC-374) * bug(fix) routes removal: added routes update on connector update (EWC-374) * bug(fix) tests (EWC-374) * bug(fix) create connectorPortService (EWC-374) * bug(fix) tests (EWC-374) * bug(fix) refactoring (EWC-374) * bug(fix) usb hal info: fixed cli usb function (EWC-449) * version 1.0.33 (#472) * test(core) unit tests for microservices service (EWC-383) (#475) * test(core) unit tests for registry service (EWC-383) (#476) * test(core) unit tests for user service (EWC-383) (#478) * bug(fix) fixed connector update & microservice deletion (EWC-455) (EWC-447) bug(fix): fix update connector Closes EWC-455 * bug(fix): fix delete microservice Closes EWC-447 --- package.json | 2 +- src/cli/iofog.js | 16 +- src/cli/microservice.js | 2 +- src/config/development.json | 3 +- src/controllers/microservices-controller.js | 2 +- src/helpers/app-helper.js | 21 +- src/helpers/error-messages.js | 3 +- .../microservice-public-mode-manager.js | 18 +- src/sequelize/managers/routing-manager.js | 16 + src/services/connector-port-service.js | 153 ++ src/services/connector-service.js | 192 +- src/services/controller-service.js | 22 +- src/services/diagnostic-service.js | 7 +- src/services/email-activation-code-service.js | 13 +- src/services/flow-service.js | 99 +- src/services/iofog-service.js | 203 +- src/services/microservices-service.js | 895 +++++---- src/services/registry-service.js | 37 +- src/services/user-service.js | 21 +- .../microservices-controller.test.js | 10 +- .../services/connector-port-service.test.js | 61 + test/src/services/connector-service.test.js | 458 +++++ test/src/services/controller-service.test.js | 101 + test/src/services/diagnostic-service.test.js | 502 +++++ .../email-activation-code-service.test.js | 179 ++ test/src/services/flow-service.test.js | 531 +++++ test/src/services/iofog-service.test.js | 1708 +++++++++++++++++ .../services/microservices-service.test.js | 1334 +++++++++++++ test/src/services/registry-service.test.js | 486 +++++ test/src/services/user-service.test.js | 694 +++++++ 30 files changed, 6980 insertions(+), 809 deletions(-) create mode 100644 src/services/connector-port-service.js create mode 100644 test/src/services/connector-port-service.test.js create mode 100644 test/src/services/connector-service.test.js create mode 100644 test/src/services/controller-service.test.js create mode 100644 test/src/services/diagnostic-service.test.js create mode 100644 test/src/services/email-activation-code-service.test.js create mode 100644 test/src/services/flow-service.test.js create mode 100644 test/src/services/iofog-service.test.js create mode 100644 test/src/services/microservices-service.test.js create mode 100644 test/src/services/registry-service.test.js create mode 100644 test/src/services/user-service.test.js diff --git a/package.json b/package.json index 88220c30e..2995967f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.32", + "version": "1.0.33", "description": "ioFog Controller project for Eclipse IoFog @ iofog.org \\nCopyright (c) 2018 Edgeworx, Inc.", "main": "./src/main.js", "author": "Saeid Baghbidi", diff --git a/src/cli/iofog.js b/src/cli/iofog.js index 8749dbb83..5a7606587 100644 --- a/src/cli/iofog.js +++ b/src/cli/iofog.js @@ -314,7 +314,7 @@ async function _deleteFog(obj, user) { } async function _getFogList(obj, user) { - const emptyFilters = [] + const emptyFilters = []; const list = await FogService.getFogList(emptyFilters, user, true); logger.info(JSON.stringify(list, null, 2)); logger.info('Fog list has been gotten successfully.'); @@ -359,8 +359,11 @@ async function _getHalHardwareInfo(obj) { logger.info("Parameters" + JSON.stringify(uuidObj)); - const info = await FogService.getHalHardwareInfo(uuidObj, {}, true); - logger.info(JSON.stringify(info, null, 2)); + const data = await FogService.getHalHardwareInfo(uuidObj, {}, true); + if (data.info) { + data.info = JSON.parse(data.info); + } + logger.info(JSON.stringify(data, null, 2)); logger.info('Hardware info has been retrieved successfully.') } @@ -371,8 +374,11 @@ async function _getHalUsbInfo(obj) { logger.info("Parameters" + JSON.stringify(uuidObj)); - const info = await FogService.getHalHardwareInfo(uuidObj, {}, true); - logger.info(JSON.stringify(info, null, 2)); + const data = await FogService.getHalUsbInfo(uuidObj, {}, true); + if (data.info) { + data.info = JSON.parse(data.info); + } + logger.info(JSON.stringify(data, null, 2)); logger.info('Usb info has been retrieved successfully.') } diff --git a/src/cli/microservice.js b/src/cli/microservice.js index 687c0fe52..812e63474 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -421,7 +421,7 @@ const _createMicroservice = async function (obj, user) { logger.info(JSON.stringify(microservice)); - const result = await MicroserviceService.createMicroserviceOnFog(microservice, user, true); + const result = await MicroserviceService.createMicroservice(microservice, user, true); logger.info(JSON.stringify(result)); logger.info('Microservice has been created successfully.'); }; diff --git a/src/config/development.json b/src/config/development.json index 9217782be..5dffbac92 100644 --- a/src/config/development.json +++ b/src/config/development.json @@ -29,5 +29,4 @@ "Diagnostics": { "DiagnosticDir": "diagnostic" } -} - +} \ No newline at end of file diff --git a/src/controllers/microservices-controller.js b/src/controllers/microservices-controller.js index e5501be60..6426854b3 100644 --- a/src/controllers/microservices-controller.js +++ b/src/controllers/microservices-controller.js @@ -20,7 +20,7 @@ const createMicroserviceOnFogEndPoint = async function (req, user) { logger.info("Parameters:" + JSON.stringify(microservice)); - return await MicroservicesService.createMicroserviceOnFog(microservice, user, false) + return await MicroservicesService.createMicroservice(microservice, user, false) }; const getMicroserviceEndPoint = async function (req, user) { diff --git a/src/helpers/app-helper.js b/src/helpers/app-helper.js index f6730b452..6dacf9799 100644 --- a/src/helpers/app-helper.js +++ b/src/helpers/app-helper.js @@ -78,13 +78,7 @@ const findAvailablePort = async function (hostname) { } let portBounds = portRange.split("-").map(i => parseInt(i)); return await portscanner.findAPortNotInUse(portBounds[0], portBounds[1], hostname); -} - -/** - * @desc generates a random String of the size specified by the input param - * @param Integer - size - * @return String - returns random string - */ +}; function isFileExists(filePath) { if (path.extname(filePath).indexOf(".") >= 0) { @@ -109,7 +103,7 @@ function isValidDomain(domain) { } const isValidPublicIP = function (publicIP) { - let re = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/; + const re = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/; return re.test(publicIP); }; @@ -142,7 +136,7 @@ function deleteUndefinedFields(obj) { } else if (obj[fld] instanceof Object) { obj[fld] = deleteUndefinedFields(obj[fld]) } - }) + }); return obj } @@ -191,11 +185,11 @@ function trimCertificate(cert) { function validateParameters(command, commandDefinitions, args) { // 1st argument = command args.shift(); - + const possibleAliasesList = _getPossibleAliasesList(command, commandDefinitions); const possibleArgsList = _getPossibleArgsList(command, commandDefinitions); - for (let arg of args) { + for (const arg of args) { // arg is [argument, alias, value] if (arg.startsWith("--")) { // argument @@ -272,14 +266,13 @@ function isTest() { } function isEmpty(obj) { - for(let key in obj) { - if(obj.hasOwnProperty(key)) + for (const key in obj) { + if (obj.hasOwnProperty(key)) return false; } return true; } - module.exports = { encryptText, decryptText, diff --git a/src/helpers/error-messages.js b/src/helpers/error-messages.js index 0ad086a46..37e68e8d7 100644 --- a/src/helpers/error-messages.js +++ b/src/helpers/error-messages.js @@ -73,5 +73,6 @@ module.exports = { INVALID_ROUTE: 'Route parsing error. Please provide valid route.' }, CONNECTOR_IS_IN_USE: 'You can\'t delete connector, because it is used for routing now.', - INVALID_VERSION_COMMAND: 'Can\'t {} version now.' + INVALID_VERSION_COMMAND_UPGRADE: 'Can\'t upgrade version now. Latest is already installed', + INVALID_VERSION_COMMAND_ROLLBACK: 'Can\'t rollback version now. There are no backups on agent' }; diff --git a/src/sequelize/managers/microservice-public-mode-manager.js b/src/sequelize/managers/microservice-public-mode-manager.js index 5d0561b69..e25e26968 100644 --- a/src/sequelize/managers/microservice-public-mode-manager.js +++ b/src/sequelize/managers/microservice-public-mode-manager.js @@ -13,12 +13,28 @@ const BaseManager = require('../managers/base-manager') const models = require('./../models'); -const MicroservicePublicMode = models.MicroservicePublicMode +const MicroservicePublicMode = models.MicroservicePublicMode; +const ConnectorPort = models.ConnectorPort; class MicroservicePublicModeManager extends BaseManager { getEntity() { return MicroservicePublicMode } + + findAllMicroservicePublicModesByConnectorId(connectorId, transaction) { + return MicroservicePublicMode.findAll({ + include: [ + { + model: ConnectorPort, + as: 'connectorPort', + required: true + } + ], + where: { + '$connectorPort.connector_id$': connectorId + } + }, {transaction: transaction}) + } } const instance = new MicroservicePublicModeManager() diff --git a/src/sequelize/managers/routing-manager.js b/src/sequelize/managers/routing-manager.js index 0ba42fd1e..df135f232 100644 --- a/src/sequelize/managers/routing-manager.js +++ b/src/sequelize/managers/routing-manager.js @@ -14,11 +14,27 @@ const BaseManager = require('./base-manager'); const models = require('./../models'); const Routing = models.Routing; +const ConnectorPort = models.ConnectorPort; class RoutingManager extends BaseManager { getEntity() { return Routing; } + + findAllRoutesByConnectorId(connectorId, transaction) { + return Routing.findAll({ + include: [ + { + model: ConnectorPort, + as: 'connectorPort', + required: true + } + ], + where: { + '$connectorPort.connector_id$': connectorId + } + }, {transaction: transaction}) + } } const instance = new RoutingManager(); diff --git a/src/services/connector-port-service.js b/src/services/connector-port-service.js new file mode 100644 index 000000000..7d8bb89ee --- /dev/null +++ b/src/services/connector-port-service.js @@ -0,0 +1,153 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2018 Edgeworx, Inc. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const ConnectorManager = require('../sequelize/managers/connector-manager'); +const https = require('https'); +const http = require('http'); +const constants = require('../helpers/constants'); +const logger = require('../logger'); +const qs = require('qs'); +const fs = require('fs'); + +async function openPortOnRandomConnector(isPublicAccess, transaction) { + let isConnectorPortOpen = false; + let ports = null; + let connector = null; + const maxAttempts = 5; + for (let i = 0; i < maxAttempts; i++) { + try { + connector = await _getRandomConnector(transaction); + ports = await _openPortsOnConnector(connector, isPublicAccess); + if (ports) { + isConnectorPortOpen = true; + break; + } + } catch (e) { + logger.warn(`Failed to open ports on Connector. Attempts ${i + 1}/${maxAttempts}`) + } + } + if (!isConnectorPortOpen) { + throw new Error('Not able to open port on remote Connector. Gave up after 5 attempts.') + } + ports.connectorId = connector.id; + return {ports: ports, connector: connector} +} + +async function _openPortsOnConnector(connector, isPublicAccess) { + let data = isPublicAccess + ? await qs.stringify({ + mapping: '{"type":"public","maxconnections":60,"heartbeatabsencethreshold":200000}' + }) + : await qs.stringify({ + mapping: '{"type":"private","maxconnectionsport1":1, "maxconnectionsport2":1, ' + + '"heartbeatabsencethresholdport1":200000, "heartbeatabsencethresholdport2":200000}' + }); + + let port = connector.devMode ? constants.CONNECTOR_HTTP_PORT : constants.CONNECTOR_HTTPS_PORT; + + let options = { + host: connector.domain, + port: port, + path: '/api/v2/mapping/add', + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': Buffer.byteLength(data) + } + }; + if (!connector.devMode && connector.cert && connector.isSelfSignedCert === true) { + const ca = fs.readFileSync(connector.cert); + options.ca = new Buffer.from(ca); + } + + const ports = await _makeRequest(connector, options, data); + return ports +} + +async function _getRandomConnector(transaction) { + const connectors = await ConnectorManager.findAll({}, transaction); + + if (connectors && connectors.length > 0) { + const randomNumber = Math.round((Math.random() * (connectors.length - 1))); + return connectors[randomNumber] + } else { + throw new Error('no connectors defined') + } +} + +async function closePortOnConnector(connector, ports) { + let data = qs.stringify({ + mappingid: ports.mappingId + }); + console.log(data); + + let port = connector.devMode ? constants.CONNECTOR_HTTP_PORT : constants.CONNECTOR_HTTPS_PORT; + + let options = { + host: connector.domain, + port: port, + path: '/api/v2/mapping/remove', + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': Buffer.byteLength(data) + } + }; + if (!connector.devMode && connector.cert && connector.isSelfSignedCert === true) { + const ca = fs.readFileSync(connector.cert); + options.ca = new Buffer.from(ca); + } + + + await _makeRequest(connector, options, data) +} + +async function _makeRequest(connector, options, data) { + return new Promise((resolve, reject) => { + let httpreq = (connector.devMode ? http : https).request(options, function (response) { + console.log(response.statusCode); + let output = ''; + response.setEncoding('utf8'); + + response.on('data', function (chunk) { + output += chunk; + }); + + response.on('end', function () { + let responseObj = JSON.parse(output); + console.log(responseObj); + if (responseObj.errormessage) { + return reject(new Error(responseObj.errormessage)); + } else { + return resolve(responseObj); + } + }); + }); + + httpreq.on('error', function (err) { + console.log(err); + if (err instanceof Error) + return reject(new Error(err.message)); + else + return reject(new Error(JSON.stringify(err))); + }); + + httpreq.write(data); + httpreq.end(); + }) +} + +module.exports = { + openPortOnRandomConnector: openPortOnRandomConnector, + closePortOnConnector: closePortOnConnector +}; diff --git a/src/services/connector-service.js b/src/services/connector-service.js index 6b8809e8e..c902fc3f8 100644 --- a/src/services/connector-service.js +++ b/src/services/connector-service.js @@ -17,23 +17,25 @@ const ConnectorManager = require('../sequelize/managers/connector-manager'); const Errors = require('../helpers/errors'); const ErrorMessages = require('../helpers/error-messages'); const AppHelper = require('../helpers/app-helper'); -const https = require('https'); -const http = require('http'); -const constants = require('../helpers/constants'); -const logger = require('../logger'); -const qs = require('qs'); const Op = require('sequelize').Op; -const fs = require('fs'); + const ConnectorPortManager = require('../sequelize/managers/connector-port-manager'); +const MicroserviceService = require('../services/microservices-service'); -async function _createConnector(connectorData, transaction) { +async function createConnector(connectorData, transaction) { await Validator.validate(connectorData, Validator.schemas.connectorCreate); - validateConnectorData(connectorData); + _validateConnectorData(connectorData); const connector = await ConnectorManager.findOne({ [Op.or]: [ - {name: connectorData.name}, - {publicIp: connectorData.publicIp}, - {domain: connectorData.domain} + { + name: connectorData.name + }, + { + publicIp: connectorData.publicIp + }, + { + domain: connectorData.domain + } ] }, transaction); if (connector) { @@ -42,29 +44,19 @@ async function _createConnector(connectorData, transaction) { return await ConnectorManager.create(connectorData, transaction) } -async function _updateConnector(connectorData, transaction) { - await Validator.validate(connectorData, Validator.schemas.connectorUpdate) - validateConnectorData(connectorData); +async function updateConnector(connectorData, transaction) { + await Validator.validate(connectorData, Validator.schemas.connectorUpdate); + _validateConnectorData(connectorData); const queryConnectorData = { publicIp: connectorData.publicIp }; - await ConnectorManager.update(queryConnectorData, connectorData, transaction) + await ConnectorManager.update(queryConnectorData, connectorData, transaction); + const connector = await ConnectorManager.findOne({publicIp: connectorData.publicIp}, transaction); + await MicroserviceService.updateRouteOverConnector(connector, transaction); + await MicroserviceService.updatePortMappingOverConnector(connector, transaction); } -function validateConnectorData(connectorData) { - if (connectorData.domain) { - const validDomain = AppHelper.isValidDomain(connectorData.domain) || AppHelper.isValidPublicIP(connectorData.domain); - if (!validDomain) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_CONNECTOR_DOMAIN, connectorData.domain)); - } - } - - if (!AppHelper.isValidPublicIP(connectorData.publicIp)) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_CONNECTOR_IP, connectorData.publicIp)); - } -} - -async function _deleteConnector(connectorData, transaction) { +async function deleteConnector(connectorData, transaction) { await Validator.validate(connectorData, Validator.schemas.connectorDelete); const queryConnectorData = { publicIp: connectorData.publicIp @@ -80,142 +72,26 @@ async function _deleteConnector(connectorData, transaction) { await ConnectorManager.delete(queryConnectorData, transaction); } -async function _getConnectorList(transaction) { +async function getConnectorList(transaction) { return await ConnectorManager.findAll({}, transaction) } -async function openPortOnRandomConnector(isPublicAccess, transaction) { - let isConnectorPortOpen = false; - let ports = null; - let connector = null; - const maxAttempts = 5; - for (let i = 0; i < maxAttempts; i++) { - try { - connector = await _getRandomConnector(transaction); - ports = await openPortsOnConnector(connector, isPublicAccess, transaction); - if (ports) { - isConnectorPortOpen = true; - break; - } - } catch (e) { - logger.warn(`Failed to open ports on comsat. Attempts ${i + 1}/${maxAttempts}`) - } - } - if (!isConnectorPortOpen) { - throw new Error('Not able to open port on remote CONNECTOR. Gave up after 5 attempts.') - } - ports.connectorId = connector.id; - return {ports: ports, connector: connector} -} - -async function _makeRequest(connector, options, data) { - return new Promise((resolve, reject) => { - let httpreq = (connector.devMode ? http : https).request(options, function (response) { - console.log(response.statusCode); - let output = ''; - response.setEncoding('utf8'); - - response.on('data', function (chunk) { - output += chunk; - }); - - response.on('end', function () { - let responseObj = JSON.parse(output); - console.log(responseObj); - if (responseObj.errormessage) { - return reject(new Error(responseObj.errormessage)); - } else { - return resolve(responseObj); - } - }); - }); - - httpreq.on('error', function (err) { - console.log(err); - if (err instanceof Error) - return reject(new Error(err.message)); - else - return reject(new Error(JSON.stringify(err))); - }); - - httpreq.write(data); - httpreq.end(); - }) -} - -async function openPortsOnConnector(connector, isPublicAccess, transaction) { - let data = isPublicAccess - ? await qs.stringify({ - mapping: '{"type":"public","maxconnections":60,"heartbeatabsencethreshold":200000}' - }) - : await qs.stringify({ - mapping: '{"type":"private","maxconnectionsport1":1, "maxconnectionsport2":1, ' + - '"heartbeatabsencethresholdport1":200000, "heartbeatabsencethresholdport2":200000}' - }); - - let port = connector.devMode ? constants.CONNECTOR_HTTP_PORT : constants.CONNECTOR_HTTPS_PORT; - - let options = { - host: connector.domain, - port: port, - path: '/api/v2/mapping/add', - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Content-Length': Buffer.byteLength(data) +function _validateConnectorData(connectorData) { + if (connectorData.domain) { + const validDomain = AppHelper.isValidDomain(connectorData.domain) || AppHelper.isValidPublicIP(connectorData.domain); + if (!validDomain) { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_CONNECTOR_DOMAIN, connectorData.domain)); } - }; - if (!connector.devMode && connector.cert && connector.isSelfSignedCert === true) { - const ca = fs.readFileSync(connector.cert); - options.ca = new Buffer.from(ca); } - const ports = await _makeRequest(connector, options, data); - return ports -} - -async function _getRandomConnector(transaction) { - const connectors = await _getConnectorList(transaction); - if (connectors && connectors.length > 0) { - const randomNumber = Math.round((Math.random() * (connectors.length - 1))); - return connectors[randomNumber] - } else { - throw new Error('no connectors defined') - } -} - -async function closePortOnConnector(connector, ports, transaction) { - let data = qs.stringify({ - mappingid: ports.mappingId - }); - console.log(data); - - let port = connector.devMode ? constants.CONNECTOR_HTTP_PORT : constants.CONNECTOR_HTTPS_PORT; - - let options = { - host: connector.domain, - port: port, - path: '/api/v2/mapping/remove', - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Content-Length': Buffer.byteLength(data) - } - }; - if (!connector.devMode && connector.cert && connector.isSelfSignedCert === true) { - const ca = fs.readFileSync(connector.cert); - options.ca = new Buffer.from(ca); + if (!AppHelper.isValidPublicIP(connectorData.publicIp)) { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_CONNECTOR_IP, connectorData.publicIp)); } - - - await _makeRequest(connector, options, data) } module.exports = { - createConnector: TransactionDecorator.generateTransaction(_createConnector), - updateConnector: TransactionDecorator.generateTransaction(_updateConnector), - deleteConnector: TransactionDecorator.generateTransaction(_deleteConnector), - getConnectorList: TransactionDecorator.generateTransaction(_getConnectorList), - openPortOnRandomConnector: openPortOnRandomConnector, - closePortOnConnector: closePortOnConnector -} \ No newline at end of file + createConnector: TransactionDecorator.generateTransaction(createConnector), + updateConnector: TransactionDecorator.generateTransaction(updateConnector), + deleteConnector: TransactionDecorator.generateTransaction(deleteConnector), + getConnectorList: TransactionDecorator.generateTransaction(getConnectorList) +}; \ No newline at end of file diff --git a/src/services/controller-service.js b/src/services/controller-service.js index 906c1cc35..d42aea13d 100644 --- a/src/services/controller-service.js +++ b/src/services/controller-service.js @@ -11,26 +11,26 @@ * */ -const FogTypesManager = require('../sequelize/managers/iofog-type-manager'); +const ioFogTypesManager = require('../sequelize/managers/iofog-type-manager'); const Config = require('../config'); const TransactionDecorator = require('../decorators/transaction-decorator'); const packageJson = require('../../package'); const getFogTypes = async function (isCLI, transaction) { - const fogTypes = await FogTypesManager.findAll({}, transaction); - let res = []; + const ioFogTypes = await ioFogTypesManager.findAll({}, transaction); + let response = []; - for (fogType of fogTypes) { - res.push({ - id: fogType.id, - name: fogType.name, - image: fogType.image, - description: fogType.description + for (ioFogType of ioFogTypes) { + response.push({ + id: ioFogType.id, + name: ioFogType.name, + image: ioFogType.image, + description: ioFogType.description }) } return { - fogTypes: res + fogTypes: response } }; @@ -59,7 +59,7 @@ const statusController = async function (isCLI) { }; const getVersion = async function (isCLI) { - return `Iofog-Controller version: ${packageJson.version}`; + return `ioFog-Controller version: ${packageJson.version}`; }; module.exports = { diff --git a/src/services/diagnostic-service.js b/src/services/diagnostic-service.js index 9e48de668..2f3349eeb 100644 --- a/src/services/diagnostic-service.js +++ b/src/services/diagnostic-service.js @@ -20,11 +20,10 @@ const MicroserviceService = require('../services/microservices-service'); const StraceDiagnosticManager = require('../sequelize/managers/strace-diagnostics-manager'); const ChangeTrackingService = require('./change-tracking-service'); const MicroserviceManager = require('../sequelize/managers/microservice-manager'); -const config = require('../config'); +const Config = require('../config'); const fs = require('fs'); const logger = require('../logger'); const ftpClient = require('ftp'); -const path = require('path'); const mime = require('mime'); @@ -60,7 +59,7 @@ const getMicroserviceStraceData = async function (uuid, data, user, isCLI, trans throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_STRACE, uuid)) } - const dir = config.get('Diagnostics:DiagnosticDir') || 'diagnostics'; + const dir = Config.get('Diagnostics:DiagnosticDir') || 'diagnostics'; const filePath = dir + '/' + uuid; let result = straceData.buffer; @@ -93,7 +92,7 @@ const postMicroserviceStraceDatatoFtp = async function (uuid, data, user, isCLI, throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_STRACE, uuid)) } - const dir = config.get('Diagnostics:DiagnosticDir'); + const dir = Config.get('Diagnostics:DiagnosticDir'); const filePath = dir + '/' + uuid; _createDirectoryIfNotExists(dir); diff --git a/src/services/email-activation-code-service.js b/src/services/email-activation-code-service.js index 1e63963d8..a79709c91 100644 --- a/src/services/email-activation-code-service.js +++ b/src/services/email-activation-code-service.js @@ -14,7 +14,6 @@ const EmailActivationCodeManager = require('../sequelize/managers/email-activation-code-manager'); const AppHelper = require('../helpers/app-helper'); const ErrorMessages = require('../helpers/error-messages'); -const TransactionDecorator = require('../decorators/transaction-decorator'); const generateActivationCode = async function (transaction) { while (true) { @@ -52,20 +51,12 @@ const verifyActivationCode = async function (activationCode, transaction) { const deleteActivationCode = async function (activationCode, transaction) { return await EmailActivationCodeManager.delete({ activationCode: activationCode - }, transaction) + }, transaction); }; -const findActivationCodeByUserId = async function (userId, transaction) { - return await EmailActivationCodeManager.findOne({ - userId: userId - }, transaction) -}; - - module.exports = { generateActivationCode: generateActivationCode, saveActivationCode: saveActivationCode, verifyActivationCode: verifyActivationCode, - deleteActivationCode: deleteActivationCode, - findActivationCodeByUserId: TransactionDecorator.generateTransaction(findActivationCodeByUserId) + deleteActivationCode: deleteActivationCode }; \ No newline at end of file diff --git a/src/services/flow-service.js b/src/services/flow-service.js index 55c446850..3ef591730 100644 --- a/src/services/flow-service.js +++ b/src/services/flow-service.js @@ -16,13 +16,15 @@ const FlowManager = require('../sequelize/managers/flow-manager'); const AppHelper = require('../helpers/app-helper'); const Errors = require('../helpers/errors'); const ErrorMessages = require('../helpers/error-messages'); -const Validation = require('../schemas'); +const Validator = require('../schemas'); const ChangeTrackingService = require('./change-tracking-service'); +const Sequelize = require('sequelize'); +const Op = Sequelize.Op; -const _createFlow = async function (flowData, user, isCLI, transaction) { - await Validation.validate(flowData, Validation.schemas.flowCreate); +const createFlow = async function (flowData, user, isCLI, transaction) { + await Validator.validate(flowData, Validator.schemas.flowCreate); - await _checkForDuplicateName(flowData.name, {}, user.id, transaction); + await _checkForDuplicateName(flowData.name, null, user.id, transaction); const flowToCreate = { name: flowData.name, @@ -40,7 +42,7 @@ const _createFlow = async function (flowData, user, isCLI, transaction) { } }; -const _deleteFlow = async function (flowId, user, isCLI, transaction) { +const deleteFlow = async function (flowId, user, isCLI, transaction) { const whereObj = { id: flowId, userId: user.id @@ -52,25 +54,10 @@ const _deleteFlow = async function (flowId, user, isCLI, transaction) { await FlowManager.delete(where, transaction); }; -async function _updateChangeTrackingsByFlowId(flowId, transaction) { - const flowWithMicroservices = await FlowManager.findFlowMicroservices({id: flowId}, transaction); - if (!flowWithMicroservices) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, flowId)); - } - const onlyUnique = (value, index, self) => self.indexOf(value) === index; - const iofogUuids = flowWithMicroservices.microservices - .map(obj => obj.iofogUuid) - .filter(onlyUnique) - .filter(val => val !== null); - for (let iofogUuid of iofogUuids) { - await ChangeTrackingService.update(iofogUuid, ChangeTrackingService.events.microserviceFull, transaction); - } -} - -const _updateFlow = async function (flowData, flowId, user, isCLI, transaction) { - await Validation.validate(flowData, Validation.schemas.flowUpdate); +const updateFlow = async function (flowData, flowId, user, isCLI, transaction) { + await Validator.validate(flowData, Validator.schemas.flowUpdate); - const oldFlow = await _getFlow(flowId, user, isCLI, transaction); + const oldFlow = await getFlow(flowId, user, isCLI, transaction); if (!oldFlow) { throw new Errors.NotFoundError(ErrorMessages.INVALID_FLOW_ID) } @@ -97,20 +84,7 @@ const _updateFlow = async function (flowData, flowId, user, isCLI, transaction) } }; -const _getFlow = async function (flowId, user, isCLI, transaction) { - const where = isCLI - ? {id: flowId} - : {id: flowId, userId: user.id}; - - const flow = await FlowManager.findOneExcludeFields(where, transaction); - - if (!flow) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, flowId)) - } - return flow -}; - -const _getUserFlows = async function (user, isCLI, transaction) { +const getUserFlows = async function (user, isCLI, transaction) { const flow = { userId: user.id }; @@ -121,17 +95,31 @@ const _getUserFlows = async function (user, isCLI, transaction) { } }; -const _getAllFlows = async function (isCLI, transaction) { +const getAllFlows = async function (isCLI, transaction) { const flows = await FlowManager.findAll({}, transaction); return { flows: flows } }; -const _checkForDuplicateName = async function (name, item, userId, transaction) { +const getFlow = async function (flowId, user, isCLI, transaction) { + const where = isCLI + ? {id: flowId} + : {id: flowId, userId: user.id}; + + const flow = await FlowManager.findOneExcludeFields(where, transaction); + + if (!flow) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, flowId)) + } + return flow +}; + + +const _checkForDuplicateName = async function (name, flowId, userId, transaction) { if (name) { - const where = item.id - ? {name: name, id: {[Op.ne]: item.id, userId: userId}} + const where = flowId + ? {name: name, id: {[Op.ne]: flowId, userId: userId}} : {name: name, userId: userId}; const result = await FlowManager.findOne(where, transaction); @@ -141,12 +129,27 @@ const _checkForDuplicateName = async function (name, item, userId, transaction) } }; +async function _updateChangeTrackingsByFlowId(flowId, transaction) { + const flowWithMicroservices = await FlowManager.findFlowMicroservices({id: flowId}, transaction); + if (!flowWithMicroservices) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, flowId)); + } + const onlyUnique = (value, index, self) => self.indexOf(value) === index; + const iofogUuids = flowWithMicroservices.microservices + .map(obj => obj.iofogUuid) + .filter(onlyUnique) + .filter(val => val !== null); + for (const iofogUuid of iofogUuids) { + await ChangeTrackingService.update(iofogUuid, ChangeTrackingService.events.microserviceFull, transaction); + } +} + module.exports = { - createFlow: TransactionDecorator.generateTransaction(_createFlow), - deleteFlow: TransactionDecorator.generateTransaction(_deleteFlow), - updateFlow: TransactionDecorator.generateTransaction(_updateFlow), - getFlowWithTransaction: TransactionDecorator.generateTransaction(_getFlow), - getUserFlows: TransactionDecorator.generateTransaction(_getUserFlows), - getAllFlows: TransactionDecorator.generateTransaction(_getAllFlows), - getFlow: _getFlow + createFlow: TransactionDecorator.generateTransaction(createFlow), + deleteFlow: TransactionDecorator.generateTransaction(deleteFlow), + updateFlow: TransactionDecorator.generateTransaction(updateFlow), + getUserFlows: TransactionDecorator.generateTransaction(getUserFlows), + getAllFlows: TransactionDecorator.generateTransaction(getAllFlows), + getFlowWithTransaction: TransactionDecorator.generateTransaction(getFlow), + getFlow: getFlow }; diff --git a/src/services/iofog-service.js b/src/services/iofog-service.js index 0776cee92..ef5002a4e 100644 --- a/src/services/iofog-service.js +++ b/src/services/iofog-service.js @@ -25,7 +25,7 @@ const USBInfoManager = require('../sequelize/managers/usb-info-manager'); const CatalogService = require('../services/catalog-service'); const MicroserviceManager = require('../sequelize/managers/microservice-manager'); -async function _createFog(fogData, user, isCli, transaction) { +async function createFog(fogData, user, isCLI, transaction) { await Validator.validate(fogData, Validator.schemas.iofogCreate); let createFogData = { @@ -71,15 +71,15 @@ async function _createFog(fogData, user, isCli, transaction) { await _createBluetoothMicroserviceForFog(fog, null, user, transaction); } - await ChangeTrackingService.update(fogData.uuid, ChangeTrackingService.events.microserviceCommon, transaction) + await ChangeTrackingService.update(createFogData.uuid, ChangeTrackingService.events.microserviceCommon, transaction); return res } -async function _updateFog(fogData, user, isCli, transaction) { +async function updateFog(fogData, user, isCLI, transaction) { await Validator.validate(fogData, Validator.schemas.iofogUpdate); - const queryFogData = isCli + const queryFogData = isCLI ? {uuid: fogData.uuid} : {uuid: fogData.uuid, userId: user.id}; @@ -118,21 +118,21 @@ async function _updateFog(fogData, user, isCli, transaction) { let msChanged = false; - if (oldFog.bluetoothEnabled === true && fogData.bluetoothEnabled === false) { - await _deleteBluetoothMicroserviceByFog(fogData, transaction); + if (oldFog.abstractedHardwareEnabled === true && fogData.abstractedHardwareEnabled === false) { + await _deleteHalMicroserviceByFog(fogData, transaction); msChanged = true; } - if (oldFog.bluetoothEnabled === false && fogData.bluetoothEnabled === true) { - await _createBluetoothMicroserviceForFog(fogData, oldFog, user, transaction); + if (oldFog.abstractedHardwareEnabled === false && fogData.abstractedHardwareEnabled === true) { + await _createHalMicroserviceForFog(fogData, oldFog, user, transaction); msChanged = true; } - if (oldFog.abstractedHardwareEnabled === true && fogData.abstractedHardwareEnabled === false) { - await _deleteHalMicroseviceByFog(fogData, transaction); + if (oldFog.bluetoothEnabled === true && fogData.bluetoothEnabled === false) { + await _deleteBluetoothMicroserviceByFog(fogData, transaction); msChanged = true; } - if (oldFog.abstractedHardwareEnabled === false && fogData.abstractedHardwareEnabled === true) { - await _createHalMicroserviceForFog(fogData, oldFog, user, transaction); + if (oldFog.bluetoothEnabled === false && fogData.bluetoothEnabled === true) { + await _createBluetoothMicroserviceForFog(fogData, oldFog, user, transaction); msChanged = true; } @@ -141,10 +141,10 @@ async function _updateFog(fogData, user, isCli, transaction) { } } -async function _deleteFog(fogData, user, isCli, transaction) { +async function deleteFog(fogData, user, isCLI, transaction) { await Validator.validate(fogData, Validator.schemas.iofogDelete); - const queryFogData = isCli + const queryFogData = isCLI ? {uuid: fogData.uuid} : {uuid: fogData.uuid, userId: user.id}; @@ -156,10 +156,10 @@ async function _deleteFog(fogData, user, isCli, transaction) { await _processDeleteCommand(fog, transaction) } -async function _getFog(fogData, user, isCli, transaction) { +async function getFog(fogData, user, isCLI, transaction) { await Validator.validate(fogData, Validator.schemas.iofogGet); - const queryFogData = isCli + const queryFogData = isCLI ? {uuid: fogData.uuid} : {uuid: fogData.uuid, userId: user.id}; @@ -167,81 +167,84 @@ async function _getFog(fogData, user, isCli, transaction) { if (!fog) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } - await _updateFogsConnectionStatus(fog, transaction); + + const updatedFog = await _updateFogsConnectionStatus(fog, transaction); return { - uuid: fog.uuid, - name: fog.name, - location: fog.location, - gpsMode: fog.gpsMode, - latitude: fog.latitude, - longitude: fog.longitude, - description: fog.description, - lastActive: fog.lastActive, - daemonStatus: fog.daemonStatus, - daemonOperatingDuration: fog.daemonOperatingDuration, - daemonLastStart: fog.daemonLastStart, - memoryUsage: fog.memoryUsage, - diskUsage: fog.diskUsage, - cpuUsage: fog.cpuUsage, - memoryViolation: fog.memoryViolation, - diskViolation: fog.diskViolation, - cpuViolation: fog.cpuViolation, - catalogItemStatus: fog.catalogItemStatus, - repositoryCount: fog.repositoryCount, - repositoryStatus: fog.repositoryStatus, - systemTime: fog.systemTime, - lastStatusTime: fog.lastStatusTime, - ipAddress: fog.ipAddress, - processedMessages: fog.processedMessages, - catalogItemMessageCounts: fog.catalogItemMessageCounts, - messageSpeed: fog.messageSpeed, - lastCommandTime: fog.lastCommandTime, - networkInterface: fog.networkInterface, - dockerUrl: fog.dockerUrl, - diskLimit: fog.diskLimit, - diskDirectory: fog.diskDirectory, - memoryLimit: fog.memoryLimit, - cpuLimit: fog.cpuLimit, - logLimit: fog.logLimit, - logDirectory: fog.logDirectory, - bluetoothEnabled: fog.bluetoothEnabled, - abstractedHardwareEnabled: fog.abstractedHardwareEnabled, - logFileCount: fog.logFileCount, - version: fog.version, - isReadyToUpgrade: fog.isReadyToUpgrade, - isReadyToRollback: fog.isReadyToRollback, - statusFrequency: fog.statusFrequency, - changeFrequency: fog.changeFrequency, - deviceScanFrequency: fog.deviceScanFrequency, - tunnel: fog.tunnel, - watchdogEnabled: fog.watchdogEnabled, - fogTypeId: fog.fogTypeId, - userId: fog.userId + uuid: updatedFog.uuid, + name: updatedFog.name, + location: updatedFog.location, + gpsMode: updatedFog.gpsMode, + latitude: updatedFog.latitude, + longitude: updatedFog.longitude, + description: updatedFog.description, + lastActive: updatedFog.lastActive, + daemonStatus: updatedFog.daemonStatus, + daemonOperatingDuration: updatedFog.daemonOperatingDuration, + daemonLastStart: updatedFog.daemonLastStart, + memoryUsage: updatedFog.memoryUsage, + diskUsage: updatedFog.diskUsage, + cpuUsage: updatedFog.cpuUsage, + memoryViolation: updatedFog.memoryViolation, + diskViolation: updatedFog.diskViolation, + cpuViolation: updatedFog.cpuViolation, + catalogItemStatus: updatedFog.catalogItemStatus, + repositoryCount: updatedFog.repositoryCount, + repositoryStatus: updatedFog.repositoryStatus, + systemTime: updatedFog.systemTime, + lastStatusTime: updatedFog.lastStatusTime, + ipAddress: updatedFog.ipAddress, + processedMessages: updatedFog.processedMessages, + catalogItemMessageCounts: updatedFog.catalogItemMessageCounts, + messageSpeed: updatedFog.messageSpeed, + lastCommandTime: updatedFog.lastCommandTime, + networkInterface: updatedFog.networkInterface, + dockerUrl: updatedFog.dockerUrl, + diskLimit: updatedFog.diskLimit, + diskDirectory: updatedFog.diskDirectory, + memoryLimit: updatedFog.memoryLimit, + cpuLimit: updatedFog.cpuLimit, + logLimit: updatedFog.logLimit, + logDirectory: updatedFog.logDirectory, + bluetoothEnabled: updatedFog.bluetoothEnabled, + abstractedHardwareEnabled: updatedFog.abstractedHardwareEnabled, + logFileCount: updatedFog.logFileCount, + version: updatedFog.version, + isReadyToUpgrade: updatedFog.isReadyToUpgrade, + isReadyToRollback: updatedFog.isReadyToRollback, + statusFrequency: updatedFog.statusFrequency, + changeFrequency: updatedFog.changeFrequency, + deviceScanFrequency: updatedFog.deviceScanFrequency, + tunnel: updatedFog.tunnel, + watchdogEnabled: updatedFog.watchdogEnabled, + fogTypeId: updatedFog.fogTypeId, + userId: updatedFog.userId }; } -async function _getFogList(filters, user, isCli, transaction) { +async function getFogList(filters, user, isCLI, transaction) { await Validator.validate(filters, Validator.schemas.iofogFilters); - const queryFogData = isCli + const queryFogData = isCLI ? {} : {userId: user.id}; let fogs = await FogManager.findAll(queryFogData, transaction); fogs = _filterFogs(fogs, filters); + const response = []; for (const fog of fogs) { - await _updateFogsConnectionStatus(fog, transaction) + const updatedFog = await _updateFogsConnectionStatus(fog, transaction); + response.push(updatedFog); } return { - fogs: fogs + fogs: response } } -async function _generateProvisioningKey(fogData, user, isCli, transaction) { +async function generateProvisioningKey(fogData, user, isCLI, transaction) { await Validator.validate(fogData, Validator.schemas.iofogGenerateProvision); - const queryFogData = isCli + const queryFogData = isCLI ? {uuid: fogData.uuid} : {uuid: fogData.uuid, userId: user.id}; @@ -263,10 +266,10 @@ async function _generateProvisioningKey(fogData, user, isCli, transaction) { } } -async function _setFogVersionCommand(fogVersionData, user, isCli, transaction) { +async function setFogVersionCommand(fogVersionData, user, isCLI, transaction) { await Validator.validate(fogVersionData, Validator.schemas.iofogSetVersionCommand); - const queryFogData = isCli + const queryFogData = isCLI ? {uuid: fogVersionData.uuid} : {uuid: fogVersionData.uuid, userId: user.id}; @@ -280,20 +283,22 @@ async function _setFogVersionCommand(fogVersionData, user, isCli, transaction) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } - if ((!fog.isReadyToRollback && fogVersionData.versionCommand === 'rollback') - || (!fog.isReadyToUpgrade && fogVersionData.versionCommand === 'upgrade')) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_VERSION_COMMAND, fogVersionData.versionCommand)) + if (!fog.isReadyToRollback && fogVersionData.versionCommand === 'rollback') { + throw new Errors.ValidationError(ErrorMessages.INVALID_VERSION_COMMAND_ROLLBACK) + } + if (!fog.isReadyToUpgrade && fogVersionData.versionCommand === 'upgrade') { + throw new Errors.ValidationError(ErrorMessages.INVALID_VERSION_COMMAND_UPGRADE) } - await _generateProvisioningKey({uuid: fogVersionData.uuid}, user, isCli, transaction); + await generateProvisioningKey({uuid: fogVersionData.uuid}, user, isCLI, transaction); await FogVersionCommandManager.updateOrCreate({iofogUuid: fogVersionData.uuid}, newVersionCommand, transaction); await ChangeTrackingService.update(fogVersionData.uuid, ChangeTrackingService.events.version, transaction) } -async function _setFogRebootCommand(fogData, user, isCli, transaction) { +async function setFogRebootCommand(fogData, user, isCLI, transaction) { await Validator.validate(fogData, Validator.schemas.iofogReboot); - const queryFogData = isCli + const queryFogData = isCLI ? {uuid: fogData.uuid} : {uuid: fogData.uuid, userId: user.id}; @@ -305,7 +310,7 @@ async function _setFogRebootCommand(fogData, user, isCli, transaction) { await ChangeTrackingService.update(fogData.uuid, ChangeTrackingService.events.reboot, transaction) } -async function _getHalHardwareInfo(uuidObj, user, isCLI, transaction) { +async function getHalHardwareInfo(uuidObj, user, isCLI, transaction) { await Validator.validate(uuidObj, Validator.schemas.halGet); const fog = await FogManager.findOne({ @@ -320,7 +325,7 @@ async function _getHalHardwareInfo(uuidObj, user, isCLI, transaction) { }, transaction); } -async function _getHalUsbInfo(uuidObj, user, isCLI, transaction) { +async function getHalUsbInfo(uuidObj, user, isCLI, transaction) { await Validator.validate(uuidObj, Validator.schemas.halGet); const fog = await FogManager.findOne({ @@ -365,12 +370,16 @@ async function _updateFogsConnectionStatus(fog, transaction) { const minInMs = 60000; const intervalInMs = fog.statusFrequency > minInMs ? fog.statusFrequency * 2 : minInMs; if (fog.daemonStatus !== 'UNKNOWN' && Date.now() - fog.lastStatusTime > intervalInMs) { - fog.daemonStatus = 'UNKNOWN'; - fog.ipAddress = '0.0.0.0'; const queryFogData = {uuid: fog.uuid}; - const toUpdate = {daemonStatus: fog.daemonStatus, ipAddress: fog.ipAddress}; - await FogManager.update(queryFogData, toUpdate, transaction) + const toUpdate = {daemonStatus: 'UNKNOWN', ipAddress: '0.0.0.0'}; + await FogManager.update(queryFogData, toUpdate, transaction); + const updatedFog = Object.assign({}, fog); + updatedFog.daemonStatus = 'UNKNOWN'; + updatedFog.ipAddress = '0.0.0.0'; + return updatedFog; } + + return fog; } async function _processDeleteCommand(fog, transaction) { @@ -399,7 +408,7 @@ async function _createHalMicroserviceForFog(fogData, oldFog, user, transaction) await MicroserviceManager.create(halMicroserviceData, transaction); } -async function _deleteHalMicroseviceByFog(fogData, transaction) { +async function _deleteHalMicroserviceByFog(fogData, transaction) { const halItem = await CatalogService.getHalCatalogItem(transaction); const deleteHalMicroserviceData = { iofogUuid: fogData.uuid, @@ -438,15 +447,15 @@ async function _deleteBluetoothMicroserviceByFog(fogData, transaction) { } module.exports = { - createFog: TransactionDecorator.generateTransaction(_createFog), - updateFog: TransactionDecorator.generateTransaction(_updateFog), - deleteFog: TransactionDecorator.generateTransaction(_deleteFog), - getFogWithTransaction: TransactionDecorator.generateTransaction(_getFog), - getFogList: TransactionDecorator.generateTransaction(_getFogList), - generateProvisioningKey: TransactionDecorator.generateTransaction(_generateProvisioningKey), - setFogVersionCommand: TransactionDecorator.generateTransaction(_setFogVersionCommand), - setFogRebootCommand: TransactionDecorator.generateTransaction(_setFogRebootCommand), - getHalHardwareInfo: TransactionDecorator.generateTransaction(_getHalHardwareInfo), - getHalUsbInfo: TransactionDecorator.generateTransaction(_getHalUsbInfo), - getFog: _getFog + createFog: TransactionDecorator.generateTransaction(createFog), + updateFog: TransactionDecorator.generateTransaction(updateFog), + deleteFog: TransactionDecorator.generateTransaction(deleteFog), + getFogWithTransaction: TransactionDecorator.generateTransaction(getFog), + getFogList: TransactionDecorator.generateTransaction(getFogList), + generateProvisioningKey: TransactionDecorator.generateTransaction(generateProvisioningKey), + setFogVersionCommand: TransactionDecorator.generateTransaction(setFogVersionCommand), + setFogRebootCommand: TransactionDecorator.generateTransaction(setFogRebootCommand), + getHalHardwareInfo: TransactionDecorator.generateTransaction(getHalHardwareInfo), + getHalUsbInfo: TransactionDecorator.generateTransaction(getHalUsbInfo), + getFog: getFog }; \ No newline at end of file diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 2207b4d04..e707df982 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -11,7 +11,7 @@ * */ -const logger = require('../logger') +const logger = require('../logger'); const TransactionDecorator = require('../decorators/transaction-decorator'); const MicroserviceManager = require('../sequelize/managers/microservice-manager'); const MicroserviceStatusManager = require('../sequelize/managers/microservice-status-manager'); @@ -22,19 +22,20 @@ const ConnectorManager = require('../sequelize/managers/connector-manager'); const ConnectorPortManager = require('../sequelize/managers/connector-port-manager'); const MicroservicePublicModeManager = require('../sequelize/managers/microservice-public-mode-manager'); const ChangeTrackingService = require('./change-tracking-service'); +const ConnectorPortService = require('./connector-port-service'); const IoFogService = require('../services/iofog-service'); const AppHelper = require('../helpers/app-helper'); const Errors = require('../helpers/errors'); const ErrorMessages = require('../helpers/error-messages'); -const Validation = require('../schemas/index'); -const ConnectorService = require('../services/connector-service'); +const Validator = require('../schemas/index'); const FlowService = require('../services/flow-service'); const CatalogService = require('../services/catalog-service'); const RoutingManager = require('../sequelize/managers/routing-manager'); const Op = require('sequelize').Op; const fs = require('fs'); +const _ = require('underscore'); -async function _listMicroservices(flowId, user, isCLI, transaction) { +async function listMicroservices(flowId, user, isCLI, transaction) { if (!isCLI) { await FlowService.getFlow(flowId, user, isCLI, transaction); } @@ -46,7 +47,7 @@ async function _listMicroservices(flowId, user, isCLI, transaction) { } } -async function _getMicroservice(microserviceUuid, user, isCLI, transaction) { +async function getMicroservice(microserviceUuid, user, isCLI, transaction) { if (!isCLI) { await _validateMicroserviceOnGet(user.id, microserviceUuid, transaction); } @@ -61,14 +62,14 @@ async function _getMicroservice(microserviceUuid, user, isCLI, transaction) { return microservice; } -async function _createMicroserviceOnFog(microserviceData, user, isCLI, transaction) { - await Validation.validate(microserviceData, Validation.schemas.microserviceCreate); +async function createMicroservice(microserviceData, user, isCLI, transaction) { + await Validator.validate(microserviceData, Validator.schemas.microserviceCreate); const microservice = await _createMicroservice(microserviceData, user, isCLI, transaction); if (microserviceData.ports) { for (const port of microserviceData.ports) { - await _createPortMapping(microservice.uuid, port, user, isCLI, transaction); + await createPortMapping(microservice.uuid, port, user, isCLI, transaction); } } if (microserviceData.volumeMappings) { @@ -90,59 +91,8 @@ async function _createMicroserviceOnFog(microserviceData, user, isCLI, transacti } } -async function _createMicroservice(microserviceData, user, isCLI, transaction) { - - let newMicroservice = { - uuid: AppHelper.generateRandomString(32), - name: microserviceData.name, - config: microserviceData.config, - catalogItemId: microserviceData.catalogItemId, - flowId: microserviceData.flowId, - iofogUuid: microserviceData.iofogUuid, - rootHostAccess: microserviceData.rootHostAccess, - logSize: microserviceData.logLimit, - userId: user.id - }; - - newMicroservice = AppHelper.deleteUndefinedFields(newMicroservice); - - await _checkForDuplicateName(newMicroservice.name, {}, user.id, transaction); - - //validate catalog item - await CatalogService.getCatalogItem(newMicroservice.catalogItemId, user, isCLI, transaction); - //validate flow - await FlowService.getFlow(newMicroservice.flowId, user, isCLI, transaction); - //validate fog node - if (newMicroservice.iofogUuid) { - await IoFogService.getFog({uuid: newMicroservice.iofogUuid}, user, isCLI, transaction); - } - - return await MicroserviceManager.create(newMicroservice, transaction); -} - -async function _createMicroserviceStatus(uuid, transaction) { - return await MicroserviceStatusManager.create({ - microserviceUuid: uuid - }, transaction); -} - -async function _createVolumeMappings(volumeMappings, microserviceUuid, transaction) { - - for (let volumeMapping of volumeMappings) { - volumeMapping.microserviceUuid = microserviceUuid - } - - await VolumeMappingManager.bulkCreate(volumeMappings, transaction) -} - -async function _createRoutes(routes, microserviceUuid, user, transaction) { - for (let route of routes) { - await _createRoute(microserviceUuid, route, user, false, transaction) - } -} - -async function _updateMicroservice(microserviceUuid, microserviceData, user, isCLI, transaction) { - await Validation.validate(microserviceData, Validation.schemas.microserviceUpdate); +async function updateMicroservice(microserviceUuid, microserviceData, user, isCLI, transaction) { + await Validator.validate(microserviceData, Validator.schemas.microserviceUpdate); const query = isCLI ? @@ -191,8 +141,8 @@ async function _updateMicroservice(microserviceUuid, microserviceData, user, isC if (microserviceDataUpdate.iofogUuid && microserviceDataUpdate.iofogUuid !== microservice.iofogUuid) { const routes = await _getLogicalNetworkRoutesByFog(microservice.iofogUuid, transaction); for (let route of routes) { - await _deleteRoute(route.sourceMicroserviceUuid, route.destMicroserviceUuid, user, isCLI, transaction); - await _createRoute(route.sourceMicroserviceUuid, route.destMicroserviceUuid, user, isCLI, transaction); + await deleteRoute(route.sourceMicroserviceUuid, route.destMicroserviceUuid, user, isCLI, transaction); + await createRoute(route.sourceMicroserviceUuid, route.destMicroserviceUuid, user, isCLI, transaction); //update change tracking for another fog in route if (microservice.iofogUuid === route.sourceIofogUuid) { await _updateChangeTracking(false, route.destIofogUuid, transaction); @@ -205,27 +155,10 @@ async function _updateMicroservice(microserviceUuid, microserviceData, user, isC } //update change tracking for new fog - await _updateChangeTracking(microserviceData.config ? true : false, microserviceDataUpdate.iofogUuid, transaction); -} - -async function _updateVolumeMappings(volumeMappings, microserviceUuid, transaction) { - for (let volumeMapping of volumeMappings) { - await VolumeMappingManager.update({ - microserviceUuid: microserviceUuid - }, volumeMapping, transaction); - } -}; - -async function _updateChangeTracking(configUpdated, fogNodeUuid, transaction) { - if (configUpdated) { - await ChangeTrackingService.update(fogNodeUuid, ChangeTrackingService.events.microserviceCommon, transaction); - } else { - await ChangeTrackingService.update(fogNodeUuid, ChangeTrackingService.events.microserviceList, transaction); - } + await _updateChangeTracking(!!microserviceData.config, microserviceDataUpdate.iofogUuid, transaction); } -async function _deleteMicroservice(microserviceUuid, microserviceData, user, isCLI, transaction) { - +async function deleteMicroservice(microserviceUuid, microserviceData, user, isCLI, transaction) { const where = isCLI ? { @@ -237,16 +170,13 @@ async function _deleteMicroservice(microserviceUuid, microserviceData, user, isC userId: user.id }; - const microservice = await MicroserviceManager.findOneWithStatus(where, transaction); if (!microservice) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)); } - await _deletePortMappings(microservice, user, transaction); - if (microservice.microserviceStatus.status === MicroserviceStates.NOT_RUNNING) { - await _deleteMicroserviceWithRoutes(microserviceUuid, transaction); + await _deleteMicroserviceWithRoutesAndPortMappings(microserviceUuid, transaction); } else { await MicroserviceManager.update({ uuid: microserviceUuid @@ -260,62 +190,15 @@ async function _deleteMicroservice(microserviceUuid, microserviceData, user, isC await _updateChangeTracking(false, microservice.iofogUuid, transaction) } -async function _deletePortMappings(microservice, user, transaction) { - const msPortMappings = await MicroservicePortManager.findAll({ - microserviceUuid: microservice.uuid - }, transaction); - - for (const msPorts of msPortMappings) { - if (msPorts.isPublic) { - await _deletePortMappingOverConnector(microservice, msPorts, user, transaction) - } else { - await _deleteSimplePortMapping(microservice, msPorts, user, transaction) - } - } -} - -async function _deleteNotRunningMicroservices(transaction) { +async function deleteNotRunningMicroservices(transaction) { const microservices = await MicroserviceManager.findAllWithStatuses(transaction); microservices .filter(microservice => microservice.delete) .filter(microservice => microservice.microserviceStatus.status === MicroserviceStates.NOT_RUNNING) - .forEach(microservice => _deleteMicroserviceWithRoutes(microservice.uuid, transaction)); -} - -async function _checkForDuplicateName(name, item, userId, transaction) { - if (name) { - const where = item.id - ? - { - name: name, - uuid: {[Op.ne]: item.id}, - userId: userId - } - : - { - name: name, - userId: userId - }; - - const result = await MicroserviceManager.findOne(where, transaction); - if (result) { - throw new Errors.DuplicatePropertyError(AppHelper.formatMessage(ErrorMessages.DUPLICATE_NAME, name)); - } - } -} - -async function _validateMicroserviceOnGet(userId, microserviceUuid, transaction) { - const where = { - '$flow.user.id$': userId, - uuid: microserviceUuid - }; - const microservice = await MicroserviceManager.findMicroserviceOnGet(where, transaction); - if (!microservice) { - throw new Errors.NotFoundError(ErrorMessages.INVALID_MICROSERVICE_USER); - } + .forEach(microservice => _deleteMicroserviceWithRoutesAndPortMappings(microservice.uuid, transaction)); } -async function _createRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, isCLI, transaction) { +async function createRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, isCLI, transaction) { const sourceWhere = isCLI ? {uuid: sourceMicroserviceUuid} : {uuid: sourceMicroserviceUuid, userId: user.id}; @@ -344,15 +227,352 @@ async function _createRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, const route = await RoutingManager.findOne({ sourceMicroserviceUuid: sourceMicroserviceUuid, destMicroserviceUuid: destMicroserviceUuid - }, transaction) + }, transaction); if (route) { throw new Errors.ValidationError('route already exists') } - if (sourceMicroservice.iofogUuid === destMicroservice.iofogUuid) { - await _createSimpleRoute(sourceMicroservice, destMicroservice, transaction) - } else { - await _createRouteOverConnector(sourceMicroservice, destMicroservice, user, transaction) + if (sourceMicroservice.iofogUuid === destMicroservice.iofogUuid) { + await _createSimpleRoute(sourceMicroservice, destMicroservice, transaction) + } else { + await _createRouteOverConnector(sourceMicroservice, destMicroservice, user, transaction) + } +} + +async function updateRouteOverConnector(connector, transaction) { + const routes = await RoutingManager.findAllRoutesByConnectorId(connector.id, transaction); + const networkMicroserviceUuids = _.flatten(_.map( + routes, route => [route.sourceNetworkMicroserviceUuid, route.destNetworkMicroserviceUuid] + )); + await _updateNetworkMicroserviceConfigs(networkMicroserviceUuids, connector, transaction); +} + +async function deleteRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, isCLI, transaction) { + const sourceWhere = isCLI + ? {uuid: sourceMicroserviceUuid} + : {uuid: sourceMicroserviceUuid, userId: user.id}; + + const sourceMicroservice = await MicroserviceManager.findOne(sourceWhere, transaction); + if (!sourceMicroservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, sourceMicroserviceUuid)) + } + + const destWhere = isCLI + ? {uuid: destMicroserviceUuid} + : {uuid: destMicroserviceUuid, userId: user.id}; + + const destMicroservice = await MicroserviceManager.findOne(destWhere, transaction); + if (!destMicroservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, destMicroserviceUuid)) + } + + const route = await RoutingManager.findOne({ + sourceMicroserviceUuid: sourceMicroserviceUuid, + destMicroserviceUuid: destMicroserviceUuid + }, transaction); + if (!route) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.ROUTE_NOT_FOUND)) + } + + if (route.isNetworkConnection) { + await _deleteRouteOverConnector(route, transaction) + } else { + await _deleteSimpleRoute(route, transaction) + } +} + +async function createPortMapping(microserviceUuid, portMappingData, user, isCLI, transaction) { + await Validator.validate(portMappingData, Validator.schemas.portsCreate); + await _validatePorts(portMappingData.internal, portMappingData.external); + + const where = isCLI + ? {uuid: microserviceUuid} + : {uuid: microserviceUuid, userId: user.id}; + + const microservice = await MicroserviceManager.findOne(where, transaction); + if (!microservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) + } + + if (!microservice.iofogUuid) { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.REQUIRED_FOG_NODE)); + } + + const msPorts = await MicroservicePortManager.findOne({ + microserviceUuid: microserviceUuid, + [Op.or]: + [ + { + portInternal: portMappingData.internal + }, + { + portExternal: portMappingData.external + } + ] + }, transaction); + if (msPorts) { + throw new Errors.ValidationError(ErrorMessages.PORT_MAPPING_ALREADY_EXISTS); + } + + if (portMappingData.publicMode) { + return await _createPortMappingOverConnector(microservice, portMappingData, user, transaction) + } else { + return await _createSimplePortMapping(microservice, portMappingData, user, transaction) + } +} + +async function updatePortMappingOverConnector(connector, transaction) { + const microservicePublicModes = await MicroservicePublicModeManager.findAllMicroservicePublicModesByConnectorId(connector.id, transaction); + const networkMicroserviceUuids = microservicePublicModes.map(obj => obj.networkMicroserviceUuid); + await _updateNetworkMicroserviceConfigs(networkMicroserviceUuids, connector, transaction); +} + +async function deletePortMapping(microserviceUuid, internalPort, user, isCLI, transaction) { + const where = isCLI + ? {uuid: microserviceUuid} + : {uuid: microserviceUuid, userId: user.id}; + + const microservice = await MicroserviceManager.findOne(where, transaction); + if (!microservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) + } + + const msPorts = await MicroservicePortManager.findOne({ + microserviceUuid: microserviceUuid, + portInternal: internalPort + }, transaction) + if (!msPorts) { + throw new Errors.NotFoundError('port mapping not exists') + } + + if (msPorts.isPublic) { + await _deletePortMappingOverConnector(microservice, msPorts, user, transaction) + } else { + await _deleteSimplePortMapping(microservice, msPorts, user, transaction) + } +} + +async function listPortMappings(microserviceUuid, user, isCLI, transaction) { + const where = isCLI + ? {uuid: microserviceUuid} + : {uuid: microserviceUuid, userId: user.id}; + const microservice = await MicroserviceManager.findOne(where, transaction) + if (!microservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) + } + + const portsPairs = await MicroservicePortManager.findAll({microserviceUuid: microserviceUuid}, transaction) + return await _buildPortsList(portsPairs, transaction) +} + +async function getPhysicalConnections(microservice, transaction) { + let res = []; + const pubModes = await MicroservicePublicModeManager.findAll({microserviceUuid: microservice.uuid}, transaction) + for (const pm of pubModes) { + res.push(pm.networkMicroserviceUuid) + } + + const sourceRoutes = await RoutingManager.findAll({sourceMicroserviceUuid: microservice.uuid}, transaction) + for (const sr of sourceRoutes) { + if (!sr.sourceIofogUuid || !sr.destIofogUuid) { + continue; + } else if (sr.sourceIofogUuid === sr.destIofogUuid) { + res.push(sr.destMicroserviceUuid) + } else if (sr.sourceIofogUuid !== sr.destIofogUuid) { + res.push(sr.sourceNetworkMicroserviceUuid) + } + } + + const netwRoutes = await RoutingManager.findAll({destNetworkMicroserviceUuid: microservice.uuid}, transaction) + for (const nr of netwRoutes) { + res.push(nr.destMicroserviceUuid) + } + + return res +} + +async function createVolumeMapping(microserviceUuid, volumeMappingData, user, isCLI, transaction) { + await Validator.validate(volumeMappingData, Validator.schemas.volumeMappings); + + const where = isCLI + ? {uuid: microserviceUuid} + : {uuid: microserviceUuid, userId: user.id}; + + const microservice = await MicroserviceManager.findOne(where, transaction); + if (!microservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) + } + + const volueMapping = await VolumeMappingManager.findOne({ + microserviceUuid: microserviceUuid, + hostDestination: volumeMappingData.hostDestination, + containerDestination: volumeMappingData.containerDestination + }, transaction); + if (volueMapping) { + throw new Errors.ValidationError(ErrorMessages.VOLUME_MAPPING_ALREADY_EXISTS); + } + + const volumeMappingObj = { + microserviceUuid: microserviceUuid, + hostDestination: volumeMappingData.hostDestination, + containerDestination: volumeMappingData.containerDestination, + accessMode: volumeMappingData.accessMode + }; + + return await VolumeMappingManager.create(volumeMappingObj, transaction); +} + +async function deleteVolumeMapping(microserviceUuid, volumeMappingUuid, user, isCLI, transaction) { + const where = isCLI + ? {uuid: microserviceUuid} + : {uuid: microserviceUuid, userId: user.id}; + + const microservice = await MicroserviceManager.findOne(where, transaction); + if (!microservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) + } + + const volumeMappingWhere = { + uuid: volumeMappingUuid, + microserviceUuid: microserviceUuid + }; + + const affectedRows = await VolumeMappingManager.delete(volumeMappingWhere, transaction); + if (affectedRows === 0) { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_VOLUME_MAPPING_UUID, volumeMappingUuid)); + } +} + +async function listVolumeMappings(microserviceUuid, user, isCLI, transaction) { + const where = isCLI + ? {uuid: microserviceUuid} + : {uuid: microserviceUuid, userId: user.id}; + const microservice = await MicroserviceManager.findOne(where, transaction); + if (!microservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) + } + + const volumeMappingWhere = { + microserviceUuid: microserviceUuid + }; + return await VolumeMappingManager.findAll(volumeMappingWhere, transaction); +} + +async function _createMicroservice(microserviceData, user, isCLI, transaction) { + + let newMicroservice = { + uuid: AppHelper.generateRandomString(32), + name: microserviceData.name, + config: microserviceData.config, + catalogItemId: microserviceData.catalogItemId, + flowId: microserviceData.flowId, + iofogUuid: microserviceData.iofogUuid, + rootHostAccess: microserviceData.rootHostAccess, + logSize: microserviceData.logLimit, + userId: user.id + }; + + newMicroservice = AppHelper.deleteUndefinedFields(newMicroservice); + + await _checkForDuplicateName(newMicroservice.name, {}, user.id, transaction); + + //validate catalog item + await CatalogService.getCatalogItem(newMicroservice.catalogItemId, user, isCLI, transaction); + //validate flow + await FlowService.getFlow(newMicroservice.flowId, user, isCLI, transaction); + //validate fog node + if (newMicroservice.iofogUuid) { + await IoFogService.getFog({uuid: newMicroservice.iofogUuid}, user, isCLI, transaction); + } + + return await MicroserviceManager.create(newMicroservice, transaction); +} + +async function _createMicroserviceStatus(uuid, transaction) { + return await MicroserviceStatusManager.create({ + microserviceUuid: uuid + }, transaction); +} + +async function _createVolumeMappings(volumeMappings, microserviceUuid, transaction) { + + const mappings = []; + for (const volumeMapping of volumeMappings) { + const mapping = Object.assign({}, volumeMapping); + mapping.microserviceUuid = microserviceUuid; + mappings.push(mapping); + } + + await VolumeMappingManager.bulkCreate(mappings, transaction) +} + +async function _createRoutes(routes, microserviceUuid, user, transaction) { + for (const route of routes) { + await createRoute(microserviceUuid, route, user, false, transaction) + } +} + +async function _updateVolumeMappings(volumeMappings, microserviceUuid, transaction) { + for (let volumeMapping of volumeMappings) { + await VolumeMappingManager.update({ + microserviceUuid: microserviceUuid + }, volumeMapping, transaction); + } +} + +async function _updateChangeTracking(configUpdated, fogNodeUuid, transaction) { + if (configUpdated) { + await ChangeTrackingService.update(fogNodeUuid, ChangeTrackingService.events.microserviceCommon, transaction); + } else { + await ChangeTrackingService.update(fogNodeUuid, ChangeTrackingService.events.microserviceList, transaction); + } +} + +//TODO use in _deleteMicroserviceWithRoutesAndPortMappings +async function _deletePortMappings(microservice, user, transaction) { + const msPortMappings = await MicroservicePortManager.findAll({ + microserviceUuid: microservice.uuid + }, transaction); + + for (const msPorts of msPortMappings) { + if (msPorts.isPublic) { + await _deletePortMappingOverConnector(microservice, msPorts, user, transaction) + } else { + await _deleteSimplePortMapping(microservice, msPorts, user, transaction) + } + } +} + +async function _checkForDuplicateName(name, item, userId, transaction) { + if (name) { + const where = item.id + ? + { + name: name, + uuid: {[Op.ne]: item.id}, + userId: userId + } + : + { + name: name, + userId: userId + }; + + const result = await MicroserviceManager.findOne(where, transaction); + if (result) { + throw new Errors.DuplicatePropertyError(AppHelper.formatMessage(ErrorMessages.DUPLICATE_NAME, name)); + } + } +} + +async function _validateMicroserviceOnGet(userId, microserviceUuid, transaction) { + const where = { + '$flow.user.id$': userId, + uuid: microserviceUuid + }; + const microservice = await MicroserviceManager.findMicroserviceOnGet(where, transaction); + if (!microservice) { + throw new Errors.NotFoundError(ErrorMessages.INVALID_MICROSERVICE_USER); } } @@ -373,18 +593,52 @@ async function _createSimpleRoute(sourceMicroservice, destMicroservice, transact destMicroserviceUuid: destMicroservice.uuid, sourceIofogUuid: sourceMicroservice.iofogUuid, destIofogUuid: destMicroservice.iofogUuid //same as sourceIofogUuid - } + }; - await RoutingManager.create(routeData, transaction) + await RoutingManager.create(routeData, transaction); await _switchOnUpdateFlagsForMicroservicesInRoute(sourceMicroservice, destMicroservice, transaction) } + +async function _updateNetworkMicroserviceConfigs(networkMicroserviceUuids, connector, transaction) { + const microservices = await MicroserviceManager.findAll({uuid: networkMicroserviceUuids}, transaction); + + let cert; + if (!connector.devMode && connector.cert) { + cert = AppHelper.trimCertificate(fs.readFileSync(connector.cert, "utf-8")) + } + + for (const microservice of microservices) { + const msConfig = JSON.parse(microservice.config); + msConfig.host = connector.domain; + msConfig.cert = cert; + msConfig.devmode = connector.devMode; + const newConfig = { + config: JSON.stringify(msConfig), + rebuild: true + }; + await MicroserviceManager.update({ + uuid: microservice.uuid + }, newConfig, transaction); + } + + const onlyUnique = (value, index, self) => self.indexOf(value) === index; + const iofogUuids = microservices + .map(obj => obj.iofogUuid) + .filter(onlyUnique) + .filter(val => val !== null); + + for (const iofogUuid of iofogUuids) { + await ChangeTrackingService.update(iofogUuid, ChangeTrackingService.events.microserviceCommon, transaction); + } +} + async function _createRouteOverConnector(sourceMicroservice, destMicroservice, user, transaction) { - //open comsat - const justOpenedConnectorsPorts = await ConnectorService.openPortOnRandomConnector(false, transaction) + //open connector + const justOpenedConnectorsPorts = await ConnectorPortService.openPortOnRandomConnector(false, transaction); - const ports = justOpenedConnectorsPorts.ports - const connector = justOpenedConnectorsPorts.connector + const ports = justOpenedConnectorsPorts.ports; + const connector = justOpenedConnectorsPorts.connector; const createConnectorPortData = { port1: ports.port1, @@ -398,9 +652,9 @@ async function _createRouteOverConnector(sourceMicroservice, destMicroservice, u connectorId: ports.connectorId, mappingId: ports.id }; - const connectorPort = await ConnectorPortManager.create(createConnectorPortData, transaction) + const connectorPort = await ConnectorPortManager.create(createConnectorPortData, transaction); - const networkCatalogItem = await CatalogService.getNetworkCatalogItem(transaction) + const networkCatalogItem = await CatalogService.getNetworkCatalogItem(transaction); let cert; if (!connector.devMode && connector.cert) { @@ -420,7 +674,7 @@ async function _createRouteOverConnector(sourceMicroservice, destMicroservice, u 'heartbeatfrequency': 20000, 'heartbeatabsencethreshold': 60000, 'devmode': connector.devMode - } + }; const sourceNetworkMicroservice = await _createNetworkMicroserviceForMaster( sourceMicroservice, sourceNetwMsConfig, @@ -442,7 +696,7 @@ async function _createRouteOverConnector(sourceMicroservice, destMicroservice, u 'heartbeatfrequency': 20000, 'heartbeatabsencethreshold': 60000, 'devmode': connector.devMode - } + }; const destNetworkMicroservice = await _createNetworkMicroserviceForMaster( destMicroservice, destNetwMsConfig, @@ -461,8 +715,8 @@ async function _createRouteOverConnector(sourceMicroservice, destMicroservice, u sourceNetworkMicroserviceUuid: sourceNetworkMicroservice.uuid, destNetworkMicroserviceUuid: destNetworkMicroservice.uuid, connectorPortId: connectorPort.id - } - await RoutingManager.create(routeData, transaction) + }; + await RoutingManager.create(routeData, transaction); await _switchOnUpdateFlagsForMicroservicesInRoute(sourceMicroservice, destMicroservice, transaction) } @@ -488,112 +742,38 @@ async function _createNetworkMicroserviceForMaster(masterMicroservice, sourceNet async function _switchOnUpdateFlagsForMicroservicesInRoute(sourceMicroservice, destMicroservice, transaction) { const updateRebuildMs = { rebuild: true - } - await MicroserviceManager.update({uuid: sourceMicroservice.uuid}, updateRebuildMs, transaction) - await MicroserviceManager.update({uuid: destMicroservice.uuid}, updateRebuildMs, transaction) - - await ChangeTrackingService.update(sourceMicroservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) - await ChangeTrackingService.update(destMicroservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) -} - -async function _deleteRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, isCLI, transaction) { - const sourceWhere = isCLI - ? {uuid: sourceMicroserviceUuid} - : {uuid: sourceMicroserviceUuid, userId: user.id}; - - const sourceMicroservice = await MicroserviceManager.findOne(sourceWhere, transaction); - if (!sourceMicroservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, sourceMicroserviceUuid)) - } - - const destWhere = isCLI - ? {uuid: destMicroserviceUuid} - : {uuid: destMicroserviceUuid, userId: user.id}; - - const destMicroservice = await MicroserviceManager.findOne(destWhere, transaction); - if (!destMicroservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, destMicroserviceUuid)) - } - - const route = await RoutingManager.findOne({ - sourceMicroserviceUuid: sourceMicroserviceUuid, - destMicroserviceUuid: destMicroserviceUuid - }, transaction) - if (!route) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.ROUTE_NOT_FOUND)) - } + }; + await MicroserviceManager.update({uuid: sourceMicroservice.uuid}, updateRebuildMs, transaction); + await MicroserviceManager.update({uuid: destMicroservice.uuid}, updateRebuildMs, transaction); - if (route.isNetworkConnection) { - await _deleteRouteOverConnector(route, transaction) - } else { - await _deleteSimpleRoute(route, transaction) - } + await ChangeTrackingService.update(sourceMicroservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction); + await ChangeTrackingService.update(destMicroservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction); } async function _deleteSimpleRoute(route, transaction) { - await RoutingManager.delete({id: route.id}, transaction) + await RoutingManager.delete({id: route.id}, transaction); - await ChangeTrackingService.update(route.sourceIofogUuid, ChangeTrackingService.events.microserviceRouting, transaction) - await ChangeTrackingService.update(route.destIofogUuid, ChangeTrackingService.events.microserviceRouting, transaction) + await ChangeTrackingService.update(route.sourceIofogUuid, ChangeTrackingService.events.microserviceRouting, transaction); + await ChangeTrackingService.update(route.destIofogUuid, ChangeTrackingService.events.microserviceRouting, transaction); } async function _deleteRouteOverConnector(route, transaction) { - const ports = await ConnectorPortManager.findOne({id: route.connectorPortId}, transaction) - const connector = await ConnectorManager.findOne({id: ports.connectorId}, transaction) + const ports = await ConnectorPortManager.findOne({id: route.connectorPortId}, transaction); + const connector = await ConnectorManager.findOne({id: ports.connectorId}, transaction); try { - await ConnectorService.closePortOnConnector(connector, ports, transaction); + await ConnectorPortService.closePortOnConnector(connector, ports); } catch (e) { logger.warn(`Can't close ports pair ${ports.mappingId} on connector ${connector.publicIp}. Delete manually if necessary`); } - await RoutingManager.delete({id: route.id}, transaction) - await ConnectorPortManager.delete({id: ports.id}, transaction) - await MicroserviceManager.delete({uuid: route.sourceNetworkMicroserviceUuid}, transaction) - await MicroserviceManager.delete({uuid: route.destNetworkMicroserviceUuid}, transaction) - - await ChangeTrackingService.update(route.sourceIofogUuid, ChangeTrackingService.events.microserviceFull, transaction) - await ChangeTrackingService.update(route.destIofogUuid, ChangeTrackingService.events.microserviceFull, transaction) -} - -async function _createPortMapping(microserviceUuid, portMappingData, user, isCLI, transaction) { - await Validation.validate(portMappingData, Validation.schemas.portsCreate); - await _validatePorts(portMappingData.internal, portMappingData.external) - - const where = isCLI - ? {uuid: microserviceUuid} - : {uuid: microserviceUuid, userId: user.id}; - - const microservice = await MicroserviceManager.findOne(where, transaction) - if (!microservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) - } - - if (!microservice.iofogUuid) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.REQUIRED_FOG_NODE)); - } - - const msPorts = await MicroservicePortManager.findOne({ - microserviceUuid: microserviceUuid, - [Op.or]: - [ - { - portInternal: portMappingData.internal - }, - { - portExternal: portMappingData.external - } - ] - }, transaction); - if (msPorts) { - throw new Errors.ValidationError(ErrorMessages.PORT_MAPPING_ALREADY_EXISTS); - } + await RoutingManager.delete({id: route.id}, transaction); + await ConnectorPortManager.delete({id: ports.id}, transaction); + await MicroserviceManager.delete({uuid: route.sourceNetworkMicroserviceUuid}, transaction); + await MicroserviceManager.delete({uuid: route.destNetworkMicroserviceUuid}, transaction); - if (portMappingData.publicMode) { - return await _createPortMappingOverConnector(microservice, portMappingData, user, transaction) - } else { - return await _createSimplePortMapping(microservice, portMappingData, user, transaction) - } + await ChangeTrackingService.update(route.sourceIofogUuid, ChangeTrackingService.events.microserviceFull, transaction); + await ChangeTrackingService.update(route.destIofogUuid, ChangeTrackingService.events.microserviceFull, transaction); } async function _createSimplePortMapping(microservice, portMappingData, user, transaction) { @@ -604,18 +784,19 @@ async function _createSimplePortMapping(microservice, portMappingData, user, tra portExternal: portMappingData.external, userId: microservice.userId, microserviceUuid: microservice.uuid - } + }; - await MicroservicePortManager.create(mappingData, transaction) + await MicroservicePortManager.create(mappingData, transaction); await _switchOnUpdateFlagsForMicroservicesForPortMapping(microservice, false, transaction) } + async function _createPortMappingOverConnector(microservice, portMappingData, user, transaction) { - //open comsat - const justOpenedConnectorsPorts = await ConnectorService.openPortOnRandomConnector(true, transaction) + //open connector + const justOpenedConnectorsPorts = await ConnectorPortService.openPortOnRandomConnector(true, transaction); - const ports = justOpenedConnectorsPorts.ports - const connector = justOpenedConnectorsPorts.connector + const ports = justOpenedConnectorsPorts.ports; + const connector = justOpenedConnectorsPorts.connector; const createConnectorPortData = { port1: ports.port1, @@ -629,9 +810,9 @@ async function _createPortMappingOverConnector(microservice, portMappingData, us connectorId: ports.connectorId, mappingId: ports.id }; - const connectorPort = await ConnectorPortManager.create(createConnectorPortData, transaction) + const connectorPort = await ConnectorPortManager.create(createConnectorPortData, transaction); - const networkCatalogItem = await CatalogService.getNetworkCatalogItem(transaction) + const networkCatalogItem = await CatalogService.getNetworkCatalogItem(transaction); let cert; if (!connector.devMode && connector.cert) { @@ -650,7 +831,7 @@ async function _createPortMappingOverConnector(microservice, portMappingData, us 'heartbeatfrequency': 20000, 'heartbeatabsencethreshold': 60000, 'devmode': connector.devMode - } + }; const networkMicroservice = await _createNetworkMicroserviceForMaster( microservice, netwMsConfig, @@ -666,9 +847,9 @@ async function _createPortMappingOverConnector(microservice, portMappingData, us portExternal: portMappingData.external, userId: microservice.userId, microserviceUuid: microservice.uuid - } + }; - const msPortMapping = await MicroservicePortManager.create(mappingData, transaction) + const msPortMapping = await MicroservicePortManager.create(mappingData, transaction); const msPubModeData = { microserviceUuid: microservice.uuid, @@ -676,11 +857,11 @@ async function _createPortMappingOverConnector(microservice, portMappingData, us iofogUuid: microservice.iofogUuid, microservicePortId: msPortMapping.id, connectorPortId: connectorPort.id - } - await MicroservicePublicModeManager.create(msPubModeData, transaction) + }; + await MicroservicePublicModeManager.create(msPubModeData, transaction); - await _switchOnUpdateFlagsForMicroservicesForPortMapping(microservice, true, transaction) + await _switchOnUpdateFlagsForMicroservicesForPortMapping(microservice, true, transaction); const publicLink = await _buildLink(connector.devMode ? 'http' : 'https', connector.publicIp, connectorPort.port2) return {publicLink: publicLink} } @@ -688,10 +869,9 @@ async function _createPortMappingOverConnector(microservice, portMappingData, us async function _switchOnUpdateFlagsForMicroservicesForPortMapping(microservice, isPublic, transaction) { const updateRebuildMs = { rebuild: true - } - await MicroserviceManager.update({uuid: microservice.uuid}, updateRebuildMs, transaction) + }; + await MicroserviceManager.update({uuid: microservice.uuid}, updateRebuildMs, transaction); - let updateChangeTrackingData = {} if (isPublic) { await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) } else { @@ -699,30 +879,6 @@ async function _switchOnUpdateFlagsForMicroservicesForPortMapping(microservice, } } -async function _deletePortMapping(microserviceUuid, internalPort, user, isCLI, transaction) { - const where = isCLI - ? {uuid: microserviceUuid} - : {uuid: microserviceUuid, userId: user.id} - - const microservice = await MicroserviceManager.findOne(where, transaction); - if (!microservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) - } - - const msPorts = await MicroservicePortManager.findOne({ - microserviceUuid: microserviceUuid, - portInternal: internalPort - }, transaction) - if (!msPorts) { - throw new Errors.NotFoundError('port mapping not exists') - } - - if (msPorts.isPublic) { - await _deletePortMappingOverConnector(microservice, msPorts, user, transaction) - } else { - await _deleteSimplePortMapping(microservice, msPorts, user, transaction) - } -} async function _deleteSimplePortMapping(microservice, msPorts, user, transaction) { await MicroservicePortManager.delete({id: msPorts.id}, transaction); @@ -741,7 +897,7 @@ async function _deletePortMappingOverConnector(microservice, msPorts, user, tran const connector = await ConnectorManager.findOne({id: ports.connectorId}, transaction); try { - await ConnectorService.closePortOnConnector(connector, ports, transaction); + await ConnectorPortService.closePortOnConnector(connector, ports); } catch (e) { logger.warn(`Can't close ports pair ${ports.mappingId} on connector ${connector.publicIp}. Delete manually if necessary`); } @@ -764,22 +920,22 @@ async function _validatePorts(internal, external) { //TODO find this ports in project. check is possible to delete some of them || external === 60400 || external === 60401 || external === 10500 || external === 54321 || external === 55555) { - throw new Errors.ValidationError('incorrect port') + throw new Errors.ValidationError('Incorrect port') } } async function _buildPortsList(portsPairs, transaction) { - const res = [] + const res = []; for (const ports of portsPairs) { let portMappingResposeData = { internal: ports.portInternal, external: ports.portExternal, publicMode: ports.isPublic - } + }; if (ports.isPublic) { - const pubMode = await MicroservicePublicModeManager.findOne({microservicePortId: ports.id}, transaction) - const connectorPorts = await ConnectorPortManager.findOne({id: pubMode.connectorPortId}, transaction) - const connector = await ConnectorManager.findOne({id: connectorPorts.connectorId}, transaction) + const pubMode = await MicroservicePublicModeManager.findOne({microservicePortId: ports.id}, transaction); + const connectorPorts = await ConnectorPortManager.findOne({id: pubMode.connectorPortId}, transaction); + const connector = await ConnectorManager.findOne({id: connectorPorts.connectorId}, transaction); portMappingResposeData.publicLink = await _buildLink(connector.devMode ? 'http' : 'https', connector.publicIp, connectorPorts.port2) } @@ -788,45 +944,6 @@ async function _buildPortsList(portsPairs, transaction) { return res } -async function _listPortMappings(microserviceUuid, user, isCLI, transaction) { - const where = isCLI - ? {uuid: microserviceUuid} - : {uuid: microserviceUuid, userId: user.id}; - const microservice = await MicroserviceManager.findOne(where, transaction) - if (!microservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) - } - - const portsPairs = await MicroservicePortManager.findAll({microserviceUuid: microserviceUuid}, transaction) - return await _buildPortsList(portsPairs, transaction) -} - -async function getPhysicalConections(microservice, transaction) { - let res = [] - const pubModes = await MicroservicePublicModeManager.findAll({microserviceUuid: microservice.uuid}, transaction) - for (const pm of pubModes) { - res.push(pm.networkMicroserviceUuid) - } - - const sourceRoutes = await RoutingManager.findAll({sourceMicroserviceUuid: microservice.uuid}, transaction) - for (const sr of sourceRoutes) { - if (!sr.sourceIofogUuid || !sr.destIofogUuid) { - continue; - } else if (sr.sourceIofogUuid === sr.destIofogUuid) { - res.push(sr.destMicroserviceUuid) - } else if (sr.sourceIofogUuid !== sr.destIofogUuid) { - res.push(sr.sourceNetworkMicroserviceUuid) - } - } - - const netwRoutes = await RoutingManager.findAll({destNetworkMicroserviceUuid: microservice.uuid}, transaction) - for (const nr of netwRoutes) { - res.push(nr.destMicroserviceUuid) - } - - return res -} - async function _getLogicalNetworkRoutesByFog(iofogUuid, transaction) { let res = []; const query = { @@ -862,7 +979,7 @@ async function _getLogicalRoutesByMicroservice(microserviceUuid, transaction) { } ] }; - const routes = await RoutingManager.findAll(query, transaction) + const routes = await RoutingManager.findAll(query, transaction); for (let route of routes) { if (route.sourceMicroserviceUuid && route.destMicroserviceUuid) { res.push(route); @@ -871,7 +988,7 @@ async function _getLogicalRoutesByMicroservice(microserviceUuid, transaction) { return res; } -async function _deleteMicroserviceWithRoutes(microserviceUuid, transaction) { +async function _deleteMicroserviceWithRoutesAndPortMappings(microserviceUuid, transaction) { const routes = await _getLogicalRoutesByMicroservice(microserviceUuid, transaction); for (let route of routes) { //TODO: simplify after splitting all endpoints service functions to validation and request processing part @@ -881,7 +998,18 @@ async function _deleteMicroserviceWithRoutes(microserviceUuid, transaction) { const user = { id: userId }; - await _deleteRoute(route.sourceMicroserviceUuid, route.destMicroserviceUuid, user, false, transaction); + await deleteRoute(route.sourceMicroserviceUuid, route.destMicroserviceUuid, user, false, transaction); + } + + const portMappings = await MicroservicePortManager.findAll({microserviceUuid: microserviceUuid}, transaction); + for (const ports of portMappings) { + const userId = (await MicroserviceManager + .findOne({uuid: ports.microserviceUuid}, transaction)) + .userId; + const user = { + id: userId + }; + await deletePortMapping(ports.microserviceUuid, ports.portInternal, user, false, transaction); } await MicroserviceManager.delete({ uuid: microserviceUuid @@ -892,87 +1020,22 @@ async function _buildLink(protocol, ip, port) { return `${protocol}://${ip}:${port}` } -async function _createVolumeMapping(microserviceUuid, volumeMappingData, user, isCLI, transaction) { - await Validation.validate(volumeMappingData, Validation.schemas.volumeMappings); - - const where = isCLI - ? {uuid: microserviceUuid} - : {uuid: microserviceUuid, userId: user.id}; - - const microservice = await MicroserviceManager.findOne(where, transaction); - if (!microservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) - } - - const volueMapping = await VolumeMappingManager.findOne({ - microserviceUuid: microserviceUuid, - hostDestination: volumeMappingData.hostDestination, - containerDestination: volumeMappingData.containerDestination - }, transaction); - if (volueMapping) { - throw new Errors.ValidationError(ErrorMessages.VOLUME_MAPPING_ALREADY_EXISTS); - } - - const volumeMappingObj = { - microserviceUuid: microserviceUuid, - hostDestination: volumeMappingData.hostDestination, - containerDestination: volumeMappingData.containerDestination, - accessMode: volumeMappingData.accessMode - }; - - return await VolumeMappingManager.create(volumeMappingObj, transaction); -} - -async function _deleteVolumeMapping(microserviceUuid, volumeMappingUuid, user, isCLI, transaction) { - const where = isCLI - ? {uuid: microserviceUuid} - : {uuid: microserviceUuid, userId: user.id}; - - const microservice = await MicroserviceManager.findOne(where, transaction); - if (!microservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) - } - - const volumeMappingWhere = { - uuid: volumeMappingUuid, - microserviceUuid: microserviceUuid - }; - - const affectedRows = await VolumeMappingManager.delete(volumeMappingWhere, transaction); - if (affectedRows === 0) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_VOLUME_MAPPING_UUID, volumeMappingUuid)); - } -} - -async function _listVolumeMappings(microserviceUuid, user, isCLI, transaction) { - const where = isCLI - ? {uuid: microserviceUuid} - : {uuid: microserviceUuid, userId: user.id}; - const microservice = await MicroserviceManager.findOne(where, transaction) - if (!microservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) - } - - const volumeMappingWhere = { - microserviceUuid: microserviceUuid - }; - return await VolumeMappingManager.findAll(volumeMappingWhere, transaction); -} - module.exports = { - createMicroserviceOnFog: TransactionDecorator.generateTransaction(_createMicroserviceOnFog), - listMicroservices: TransactionDecorator.generateTransaction(_listMicroservices), - getMicroservice: TransactionDecorator.generateTransaction(_getMicroservice), - updateMicroservice: TransactionDecorator.generateTransaction(_updateMicroservice), - deleteMicroservice: TransactionDecorator.generateTransaction(_deleteMicroservice), - createRoute: TransactionDecorator.generateTransaction(_createRoute), - deleteRoute: TransactionDecorator.generateTransaction(_deleteRoute), - createPortMapping: TransactionDecorator.generateTransaction(_createPortMapping), - listMicroservicePortMappings: TransactionDecorator.generateTransaction(_listPortMappings), - deletePortMapping: TransactionDecorator.generateTransaction(_deletePortMapping), - createVolumeMapping: TransactionDecorator.generateTransaction(_createVolumeMapping), - deleteVolumeMapping: TransactionDecorator.generateTransaction(_deleteVolumeMapping), - listVolumeMappings: TransactionDecorator.generateTransaction(_listVolumeMappings), - getPhysicalConnections: getPhysicalConections, - deleteNotRunningMicroservices: _deleteNotRunningMicroservices + createMicroservice: TransactionDecorator.generateTransaction(createMicroservice), + listMicroservices: TransactionDecorator.generateTransaction(listMicroservices), + getMicroservice: TransactionDecorator.generateTransaction(getMicroservice), + updateMicroservice: TransactionDecorator.generateTransaction(updateMicroservice), + deleteMicroservice: TransactionDecorator.generateTransaction(deleteMicroservice), + createRoute: TransactionDecorator.generateTransaction(createRoute), + deleteRoute: TransactionDecorator.generateTransaction(deleteRoute), + createPortMapping: TransactionDecorator.generateTransaction(createPortMapping), + listMicroservicePortMappings: TransactionDecorator.generateTransaction(listPortMappings), + deletePortMapping: TransactionDecorator.generateTransaction(deletePortMapping), + createVolumeMapping: TransactionDecorator.generateTransaction(createVolumeMapping), + deleteVolumeMapping: TransactionDecorator.generateTransaction(deleteVolumeMapping), + listVolumeMappings: TransactionDecorator.generateTransaction(listVolumeMappings), + getPhysicalConnections: getPhysicalConnections, + deleteNotRunningMicroservices: deleteNotRunningMicroservices, + updateRouteOverConnector: updateRouteOverConnector, + updatePortMappingOverConnector: updatePortMappingOverConnector }; diff --git a/src/services/registry-service.js b/src/services/registry-service.js index 5d3c44737..730cba299 100644 --- a/src/services/registry-service.js +++ b/src/services/registry-service.js @@ -43,21 +43,16 @@ const createRegistry = async function (registry, user, transaction) { registryCreate = AppHelper.deleteUndefinedFields(registryCreate); const createdRegistry = await RegistryManager.create(registryCreate, transaction); - await updateChangeTracking(user, transaction); + + await _updateChangeTracking(user, transaction); + return { id: createdRegistry.id } }; -const updateChangeTracking = async function (user, transaction) { - let fogs = await FogManager.findAll({userId: user.id}, transaction); - for (fog of fogs) { - await ChangeTrackingService.update(fog.uuid, ChangeTrackingService.events.registries, transaction); - } -}; - -const findRegistries = async function (user, isCli, transaction) { - const queryRegistry = isCli +const findRegistries = async function (user, isCLI, transaction) { + const queryRegistry = isCLI ? {} : { [Op.or]: @@ -77,20 +72,20 @@ const findRegistries = async function (user, isCli, transaction) { } }; -const deleteRegistry = async function (registryData, user, isCli, transaction) { - await Validator.validate(registryData, Validator.schemas.registryDelete) - const queryData = isCli +const deleteRegistry = async function (registryData, user, isCLI, transaction) { + await Validator.validate(registryData, Validator.schemas.registryDelete); + const queryData = isCLI ? {id: registryData.id} : {id: registryData.id, userId: user.id}; const registry = await RegistryManager.findOne(queryData, transaction); if (!registry) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_REGISTRY_ID, registryData.id)); } - if (isCli) { + if (isCLI) { user = {id: registry.userId}; } await RegistryManager.delete(queryData, transaction); - await updateChangeTracking(user, transaction); + await _updateChangeTracking(user, transaction); }; const updateRegistry = async function (registry, registryId, user, isCLI, transaction) { @@ -131,12 +126,20 @@ const updateRegistry = async function (registry, registryId, user, isCLI, transa await RegistryManager.update(where, registryUpdate, transaction); - await updateChangeTracking(user, transaction); + await _updateChangeTracking(user, transaction); +}; + + +const _updateChangeTracking = async function (user, transaction) { + let fogs = await FogManager.findAll({userId: user.id}, transaction); + for (fog of fogs) { + await ChangeTrackingService.update(fog.uuid, ChangeTrackingService.events.registries, transaction); + } }; module.exports = { - findRegistries: TransactionDecorator.generateTransaction(findRegistries), createRegistry: TransactionDecorator.generateTransaction(createRegistry), + findRegistries: TransactionDecorator.generateTransaction(findRegistries), deleteRegistry: TransactionDecorator.generateTransaction(deleteRegistry), updateRegistry: TransactionDecorator.generateTransaction(updateRegistry) }; \ No newline at end of file diff --git a/src/services/user-service.js b/src/services/user-service.js index 53224dbeb..1d9a5456b 100644 --- a/src/services/user-service.js +++ b/src/services/user-service.js @@ -19,28 +19,19 @@ const Errors = require('../helpers/errors'); const ErrorMessages = require('../helpers/error-messages'); const Config = require('../config'); const ioFogManager = require('../sequelize/managers/iofog-manager'); - const emailActivationTemplate = require('../views/email-activation-temp'); const emailRecoveryTemplate = require('../views/email-temp'); const emailResetTemplate = require('../views/reset-password-temp'); const EmailActivationCodeService = require('./email-activation-code-service'); - const AccessTokenService = require('./access-token-service'); const TransactionDecorator = require('../decorators/transaction-decorator'); - const Validator = require('../schemas'); -const createUser = async function (user, transaction) { - return await UserManager.create(user, transaction) -}; - const signUp = async function (user, isCLI, transaction) { - let isEmailActivationEnabled = Config.get("Email:ActivationEnabled"); if (isEmailActivationEnabled) { - const newUser = await _handleCreateUser(user, isEmailActivationEnabled, transaction); const activationCodeData = await EmailActivationCodeService.generateActivationCode(transaction); @@ -56,7 +47,6 @@ const signUp = async function (user, isCLI, transaction) { }; const login = async function (credentials, isCLI, transaction) { - const user = await UserManager.findOne({ email: credentials.email }, transaction); @@ -138,7 +128,7 @@ const logout = async function (user, isCLI, transaction) { return await AccessTokenService.removeAccessTokenByUserId(user.id, transaction) }; -const updateDetails = async function (user, profileData, isCLI, transaction) { +const updateUserDetails = async function (user, profileData, isCLI, transaction) { if (isCLI) { await Validator.validate(profileData, Validator.schemas.updateUserProfileCLI); } else { @@ -147,7 +137,7 @@ const updateDetails = async function (user, profileData, isCLI, transaction) { const password = (profileData.password) ? AppHelper.encryptText(profileData.password, user.email) : undefined; - const updateObject = isCLI ? + let updateObject = isCLI ? { firstName: profileData.firstName, lastName: profileData.lastName, @@ -159,7 +149,7 @@ const updateDetails = async function (user, profileData, isCLI, transaction) { lastName: profileData.lastName }; - AppHelper.deleteUndefinedFields(updateObject); + updateObject = AppHelper.deleteUndefinedFields(updateObject); await UserManager.updateDetails(user, updateObject, transaction); @@ -171,7 +161,6 @@ const updateDetails = async function (user, profileData, isCLI, transaction) { }; const deleteUser = async function (force, user, isCLI, transaction) { - if (!force) { const ioFogArray = await ioFogManager.findAll({ userId: user.id @@ -321,7 +310,7 @@ async function _handleCreateUser(user, isEmailActivationEnabled, transaction) { async function _createNewUser(user, isEmailActivationEnabled, transaction) { user.emailActivated = !isEmailActivationEnabled; - return await createUser(user, transaction) + return await UserManager.create(user, transaction); } async function _notifyUserAboutActivationCode(email, url, emailSenderData, activationCodeData, transporter) { @@ -390,7 +379,7 @@ module.exports = { resendActivation: TransactionDecorator.generateTransaction(resendActivation), activateUser: TransactionDecorator.generateTransaction(activateUser), logout: TransactionDecorator.generateTransaction(logout), - updateUserDetails: TransactionDecorator.generateTransaction(updateDetails), + updateUserDetails: TransactionDecorator.generateTransaction(updateUserDetails), deleteUser: TransactionDecorator.generateTransaction(deleteUser), updateUserPassword: TransactionDecorator.generateTransaction(updateUserPassword), resetUserPassword: TransactionDecorator.generateTransaction(resetUserPassword), diff --git a/test/src/controllers/microservices-controller.test.js b/test/src/controllers/microservices-controller.test.js index 3baa7d889..897400c65 100644 --- a/test/src/controllers/microservices-controller.test.js +++ b/test/src/controllers/microservices-controller.test.js @@ -55,12 +55,12 @@ describe('Microservices Controller', () => { def('subject', () => $subject.createMicroserviceOnFogEndPoint($req, $user)); beforeEach(() => { - $sandbox.stub(MicroservicesService, 'createMicroserviceOnFog').returns($response); + $sandbox.stub(MicroservicesService, 'createMicroservice').returns($response); }); - it('calls MicroservicesService.createMicroserviceOnFog with correct args', async () => { + it('calls MicroservicesService.createMicroservice with correct args', async () => { await $subject; - expect(MicroservicesService.createMicroserviceOnFog).to.have.been.calledWith({ + expect(MicroservicesService.createMicroservice).to.have.been.calledWith({ name: $name, config: $config, catalogItemId: $catalogItemId, @@ -74,7 +74,7 @@ describe('Microservices Controller', () => { }, $user, false); }); - context('when MicroservicesService#createMicroserviceOnFog fails', () => { + context('when MicroservicesService#createMicroservice fails', () => { const error = 'Error!'; def('response', () => Promise.reject(error)); @@ -84,7 +84,7 @@ describe('Microservices Controller', () => { }) }); - context('when MicroservicesService#createMicroserviceOnFog succeeds', () => { + context('when MicroservicesService#createMicroservice succeeds', () => { it(`succeeds`, () => { return expect($subject).to.eventually.equal(undefined) }) diff --git a/test/src/services/connector-port-service.test.js b/test/src/services/connector-port-service.test.js new file mode 100644 index 000000000..c2cb72e22 --- /dev/null +++ b/test/src/services/connector-port-service.test.js @@ -0,0 +1,61 @@ +// TODO finish with qs.stringify mock EWC-452 +// describe('.openPortOnRandomConnector()', () => { +// const transaction = {}; +// const error = 'Error!'; +// +// const isPublicAccess = false; +// +// const connectors = [ +// { +// id: 15 +// }, +// { +// id: 16 +// } +// ]; +// +// def('subject', () => $subject.openPortOnRandomConnector(isPublicAccess, transaction)); +// def('findConnectorsResponse', () => Promise.resolve(connectors)); +// def('stringifyResponse', () => Promise.resolve()); +// +// beforeEach(() => { +// $sandbox.stub(ConnectorManager, 'findAll').returns($findConnectorsResponse); +// $sandbox.stub(qs, 'stringify').returns($stringifyResponse); +// }); +// +// it('calls ConnectorManager#findAll() with correct args', async () => { +// await $subject; +// expect(ConnectorManager.findAll).to.have.been.calledWith({}, transaction); +// }); +// +// context('when ConnectorManager#findAll() fails', () => { +// def('findConnectorsResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error) +// }) +// }); +// +// context('when ConnectorManager#findAll() succeeds', () => { +// it('calls qs#stringify() with correct args', async () => { +// await $subject; +// expect(qs.stringify).to.have.been.calledWith({ +// mapping: '{"type":"public","maxconnections":60,"heartbeatabsencethreshold":200000}' +// }); +// }); +// +// context('when qs#stringify() fails', () => { +// def('stringifyResponse', () => error); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.eventually.equal(undefined) +// }) +// }); +// +// context('when qs#stringify() succeeds', () => { +// it('fulfills the promise', () => { +// return expect($subject).to.eventually.equal(undefined) +// }) +// }) +// }) +// }); \ No newline at end of file diff --git a/test/src/services/connector-service.test.js b/test/src/services/connector-service.test.js new file mode 100644 index 000000000..0b98128e3 --- /dev/null +++ b/test/src/services/connector-service.test.js @@ -0,0 +1,458 @@ +const {expect} = require('chai'); +const sinon = require('sinon'); + +const ConnectorManager = require('../../../src/sequelize/managers/connector-manager'); +const MicroserviceService = require('../../../src/services/microservices-service'); +const ConnectorService = require('../../../src/services/connector-service'); +const Validator = require('../../../src/schemas'); +const AppHelper = require('../../../src/helpers/app-helper'); +const ConnectorPortManager = require('../../../src/sequelize/managers/connector-port-manager'); +const Sequelize = require('sequelize'); +const Op = Sequelize.Op; +const qs = require('qs'); + +describe('Connector Service', () => { + def('subject', () => ConnectorService); + def('sandbox', () => sinon.createSandbox()); + + afterEach(() => $sandbox.restore()); + + describe('.createConnector()', () => { + const transaction = {}; + const error = 'Error!'; + + const connectorData = { + name: 'testName', + domain: 'testDomain', + publicIp: 'testPublicIp', + cert: 'testCert', + isSelfSignedCert: false, + devMode: true + }; + + def('subject', () => $subject.createConnector(connectorData, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('isValidDomainResponse', () => false); + def('isValidPublicIpResponse', () => true); + def('isValidPublicIpResponse2', () => true); + def('findConnectorResponse', () => Promise.resolve()); + def('createConnectorResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(AppHelper, 'isValidDomain').returns($isValidDomainResponse); + $sandbox.stub(AppHelper, 'isValidPublicIP') + .onFirstCall().returns($isValidPublicIpResponse) + .onSecondCall().returns($isValidPublicIpResponse2); + $sandbox.stub(ConnectorManager, 'findOne').returns($findConnectorResponse); + $sandbox.stub(ConnectorManager, 'create').returns($createConnectorResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(connectorData, Validator.schemas.connectorCreate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls AppHelper#isValidDomain() with correct args', async () => { + await $subject; + expect(AppHelper.isValidDomain).to.have.been.calledWith(connectorData.domain); + }); + + context('when AppHelper#isValidDomain() fails', () => { + def('isValidDomainResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined) + }) + }); + + context('when AppHelper#isValidDomain() succeeds', () => { + it('calls AppHelper#isValidPublicIP() with correct args', async () => { + await $subject; + expect(AppHelper.isValidPublicIP).to.have.been.calledWith(connectorData.domain); + }); + + context('when AppHelper#isValidPublicIP() fails', () => { + def('isValidPublicIpResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined) + }) + }); + + context('when AppHelper#isValidPublicIP() succeeds', () => { + it('calls AppHelper#isValidPublicIP() with correct args', async () => { + await $subject; + expect(AppHelper.isValidPublicIP).to.have.been.calledWith(connectorData.publicIp); + }); + + context('when AppHelper#isValidPublicIP() fails', () => { + def('isValidPublicIpResponse2', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined) + }) + }); + + context('when AppHelper#isValidPublicIP() succeeds', () => { + it('calls ConnectorManager#findOne() with correct args', async () => { + await $subject; + expect(ConnectorManager.findOne).to.have.been.calledWith({ + [Op.or]: [ + { + name: connectorData.name + }, + { + publicIp: connectorData.publicIp + }, + { + domain: connectorData.domain + } + ] + }, transaction); + }); + + context('when ConnectorManager#findOne() fails', () => { + def('findConnectorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when ConnectorManager#findOne() succeeds', () => { + it('calls ConnectorManager#create() with correct args', async () => { + await $subject; + expect(ConnectorManager.create).to.have.been.calledWith(connectorData, transaction); + }); + + context('when ConnectorManager#create() fails', () => { + def('createConnectorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when ConnectorManager#create() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined) + }) + }) + }) + }) + }) + }) + }) + }); + + describe('.updateConnector()', () => { + const transaction = {}; + const error = 'Error!'; + + const connectorData = { + name: 'testName', + domain: 'testDomain', + publicIp: 'testPublicIp', + cert: 'testCert', + isSelfSignedCert: false, + devMode: true + }; + + const connector = {}; + + def('subject', () => $subject.updateConnector(connectorData, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('isValidDomainResponse', () => false); + def('isValidPublicIpResponse', () => true); + def('isValidPublicIpResponse2', () => true); + def('updateConnectorResponse', () => Promise.resolve()); + def('findOneConnectorResponse', () => Promise.resolve(connector)); + def('updateRouteOverConnectorResponse', () => Promise.resolve()); + def('updatePortMappingOverConnectorResponse', () => Promise.resolve()); + + const queryConnectorData = { + publicIp: connectorData.publicIp + }; + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(AppHelper, 'isValidDomain').returns($isValidDomainResponse); + $sandbox.stub(AppHelper, 'isValidPublicIP') + .onFirstCall().returns($isValidPublicIpResponse) + .onSecondCall().returns($isValidPublicIpResponse2); + $sandbox.stub(ConnectorManager, 'update').returns($updateConnectorResponse); + $sandbox.stub(ConnectorManager, 'findOne').returns($findOneConnectorResponse); + $sandbox.stub(MicroserviceService, 'updateRouteOverConnector').returns($updateRouteOverConnectorResponse); + $sandbox.stub(MicroserviceService, 'updatePortMappingOverConnector').returns($updatePortMappingOverConnectorResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(connectorData, Validator.schemas.connectorUpdate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls AppHelper#isValidDomain() with correct args', async () => { + await $subject; + expect(AppHelper.isValidDomain).to.have.been.calledWith(connectorData.domain); + }); + + context('when AppHelper#isValidDomain() fails', () => { + def('isValidDomainResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined) + }) + }); + + context('when AppHelper#isValidDomain() succeeds', () => { + it('calls AppHelper#isValidPublicIP() with correct args', async () => { + await $subject; + expect(AppHelper.isValidPublicIP).to.have.been.calledWith(connectorData.domain); + }); + + context('when AppHelper#isValidPublicIP() fails', () => { + def('isValidPublicIpResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined) + }) + }); + + context('when AppHelper#isValidPublicIP() succeeds', () => { + it('calls AppHelper#isValidPublicIP() with correct args', async () => { + await $subject; + expect(AppHelper.isValidPublicIP).to.have.been.calledWith(connectorData.publicIp); + }); + + context('when AppHelper#isValidPublicIP() fails', () => { + def('isValidPublicIpResponse2', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined) + }) + }); + + context('when AppHelper#isValidPublicIP() succeeds', () => { + it('calls ConnectorManager#update() with correct args', async () => { + await $subject; + expect(ConnectorManager.update).to.have.been.calledWith(queryConnectorData, connectorData, transaction); + }); + + context('when ConnectorManager#update() fails', () => { + def('updateConnectorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when ConnectorManager#update() succeeds', () => { + it('calls ConnectorManager#findOne() with correct args', async () => { + await $subject; + expect(ConnectorManager.findOne).to.have.been.calledWith({ + publicIp: connectorData.publicIp + }, transaction); + }); + + context('when ConnectorManager#findOne() fails', () => { + def('findOneConnectorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when ConnectorManager#findOne() succeeds', () => { + it('calls MicroserviceService#updateRouteOverConnector() with correct args', async () => { + await $subject; + expect(MicroserviceService.updateRouteOverConnector).to.have.been.calledWith(connector, transaction); + }); + + context('when MicroserviceService#updateRouteOverConnector() fails', () => { + def('updateRouteOverConnectorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when MicroserviceService#updateRouteOverConnector() succeeds', () => { + it('calls MicroserviceService#updatePortMappingOverConnector() with correct args', async () => { + await $subject; + expect(MicroserviceService.updatePortMappingOverConnector).to.have.been.calledWith(connector, transaction); + }); + + context('when MicroserviceService#updatePortMappingOverConnector() fails', () => { + def('updatePortMappingOverConnectorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when MicroserviceService#updatePortMappingOverConnector() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }); + + describe('.deleteConnector()', () => { + const transaction = {}; + const error = 'Error!'; + + const connectorData = { + name: 'testName', + domain: 'testDomain', + publicIp: 'testPublicIp', + cert: 'testCert', + isSelfSignedCert: false, + devMode: true + }; + + const connector = { + id: 15 + }; + + def('subject', () => $subject.deleteConnector(connectorData, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findConnectorResponse', () => Promise.resolve(connector)); + def('findConnectorPortsResponse', () => Promise.resolve()); + def('deleteConnectorResponse', () => Promise.resolve()); + + const queryConnectorData = { + publicIp: connectorData.publicIp + }; + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(ConnectorManager, 'findOne').returns($findConnectorResponse); + $sandbox.stub(ConnectorPortManager, 'findAll').returns($findConnectorPortsResponse); + $sandbox.stub(ConnectorManager, 'delete').returns($deleteConnectorResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(connectorData, Validator.schemas.connectorDelete); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls ConnectorManager#findOne() with correct args', async () => { + await $subject; + expect(ConnectorManager.findOne).to.have.been.calledWith(queryConnectorData, transaction); + }); + + context('when ConnectorManager#findOne() fails', () => { + def('findConnectorResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined) + }) + }); + + context('when ConnectorManager#findOne() succeeds', () => { + it('calls ConnectorPortManager#findAll() with correct args', async () => { + await $subject; + expect(ConnectorPortManager.findAll).to.have.been.calledWith({ + connectorId: connector.id + }, transaction); + }); + + context('when ConnectorPortManager#findAll() fails', () => { + def('findConnectorPortsResponse', () => { + }); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined) + }) + }); + + context('when ConnectorPortManager#findAll() succeeds', () => { + it('calls ConnectorManager#delete() with correct args', async () => { + await $subject; + expect(ConnectorManager.delete).to.have.been.calledWith(queryConnectorData, transaction); + }); + + context('when ConnectorManager#delete() fails', () => { + def('deleteConnectorResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined) + }) + }); + + context('when ConnectorManager#delete() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined) + }) + }) + }) + }) + }) + }); + + describe('.getConnectorList()', () => { + const transaction = {}; + const error = 'Error!'; + + def('subject', () => $subject.getConnectorList(transaction)); + def('findConnectorsResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(ConnectorManager, 'findAll').returns($findConnectorsResponse); + }); + + it('calls ConnectorManager#findAll() with correct args', async () => { + await $subject; + expect(ConnectorManager.findAll).to.have.been.calledWith({}, transaction); + }); + + context('when ConnectorManager#findAll() fails', () => { + def('findConnectorsResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when ConnectorManager#findAll() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined) + }) + }) + }); +}); \ No newline at end of file diff --git a/test/src/services/controller-service.test.js b/test/src/services/controller-service.test.js new file mode 100644 index 000000000..98650722c --- /dev/null +++ b/test/src/services/controller-service.test.js @@ -0,0 +1,101 @@ +const {expect} = require('chai'); +const sinon = require('sinon'); + +const ControllerService = require('../../../src/services/controller-service'); +const ioFogTypesManager = require('../../../src/sequelize/managers/iofog-type-manager'); +const Config = require('../../../src/config'); + +describe('Controller Service', () => { + def('subject', () => ControllerService); + def('sandbox', () => sinon.createSandbox()); + + afterEach(() => $sandbox.restore()); + + const isCLI = false; + + describe('.getFogTypes()', () => { + const transaction = {}; + const error = 'Error!'; + + def('subject', () => $subject.getFogTypes(isCLI, transaction)); + def('findResponse', () => Promise.resolve([{ + id: 15, + name: 'testName', + image: 'testImage', + description: 'testDescription' + }])); + + beforeEach(() => { + $sandbox.stub(ioFogTypesManager, 'findAll').returns($findResponse); + }); + + it('calls ioFogTypesManager#findAll() with correct args', async () => { + await $subject; + expect(ioFogTypesManager.findAll).to.have.been.calledWith({}, transaction); + }); + + context('when ioFogTypesManager#findAll() fails', () => { + def('findResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when ioFogTypesManager#findAll() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('fogTypes') + }) + }) + }); + + describe('.emailActivation()', () => { + const error = 'Error!'; + + def('subject', () => $subject.emailActivation(isCLI)); + def('getResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(Config, 'get').returns($getResponse); + }); + + it('calls Config#get() with correct args', async () => { + await $subject; + expect(Config.get).to.have.been.calledWith('Email:ActivationEnabled'); + }); + + context('when Config#get() fails', () => { + def('getResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when Config#get() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('isEmailActivationEnabled') + }) + }) + }); + + + describe('.statusController()', () => { + const error = 'Error!'; + + def('subject', () => $subject.statusController(isCLI)); + def('getResponse', () => Promise.resolve()); + + beforeEach(() => { + // TODO daemon.status + //$sandbox.stub(daemon, 'status').returns($getResponse); + }); + + // it('Returns valid status', () => { + // return expect($subject).to.have.property('status') && + // expect($subject).to.have.property('timestamp') + // }) + }); + + +}); \ No newline at end of file diff --git a/test/src/services/diagnostic-service.test.js b/test/src/services/diagnostic-service.test.js new file mode 100644 index 000000000..d18b303cf --- /dev/null +++ b/test/src/services/diagnostic-service.test.js @@ -0,0 +1,502 @@ +const {expect} = require('chai'); +const sinon = require('sinon'); + +const StraceDiagnosticManager = require('../../../src/sequelize/managers/strace-diagnostics-manager'); +const DiagnosticService = require('../../../src/services/diagnostic-service'); +const MicroserviceService = require('../../../src/services/microservices-service'); +const ChangeTrackingService = require('../../../src/services/change-tracking-service'); +const Validator = require('../../../src/schemas'); +const MicroserviceManager = require('../../../src/sequelize/managers/microservice-manager'); +const Config = require('../../../src/config'); + +describe('DiagnosticService Service', () => { + def('subject', () => DiagnosticService); + def('sandbox', () => sinon.createSandbox()); + + const isCLI = true; + + afterEach(() => $sandbox.restore()); + + describe('.changeMicroserviceStraceState()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = 'user!'; + + const uuid = 'testUuid'; + + const data = { + enable: true + }; + + const straceObj = { + straceRun: data.enable, + microserviceUuid: uuid + }; + + const microservice = { + iofogUuid: 'testIoFogUuid' + }; + + def('subject', () => $subject.changeMicroserviceStraceState(uuid, data, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('getMicroserviceResponse', () => Promise.resolve(microservice)); + def('updateOrCreateDiagnosticResponse', () => Promise.resolve()); + def('updateChangeTrackingResponse', () => Promise.resolve()); + + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(MicroserviceService, 'getMicroservice').returns($getMicroserviceResponse); + $sandbox.stub(StraceDiagnosticManager, 'updateOrCreate').returns($updateOrCreateDiagnosticResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(data, Validator.schemas.straceStateUpdate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls MicroserviceService#getMicroservice() with correct args', async () => { + await $subject; + expect(MicroserviceService.getMicroservice).to.have.been.calledWith(uuid, user, isCLI, transaction); + }); + + context('when MicroserviceService#getMicroservice() fails', () => { + def('getMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when MicroserviceService#getMicroservice() succeeds', () => { + it('calls StraceDiagnosticManager#updateOrCreate() with correct args', async () => { + await $subject; + expect(StraceDiagnosticManager.updateOrCreate).to.have.been.calledWith({ + microserviceUuid: uuid + }, straceObj, transaction); + }); + + context('when StraceDiagnosticManager#updateOrCreate() fails', () => { + def('updateOrCreateDiagnosticResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when StraceDiagnosticManager#updateOrCreate() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + expect(ChangeTrackingService.update).to.have.been.calledWith(microservice.iofogUuid, + ChangeTrackingService.events.diagnostics, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined) + }) + }) + }) + }) + }) + }); + + describe('.getMicroserviceStraceData()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const uuid = 'testUuid'; + + const data = { + format: 'string' + }; + + const microservice = { + iofogUuid: 'testIoFogUuid' + }; + + def('subject', () => $subject.getMicroserviceStraceData(uuid, data, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('getMicroserviceResponse', () => Promise.resolve(microservice)); + def('findStraceResponse', () => Promise.resolve({})); + def('configGetResponse', () => Promise.resolve()); + + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(MicroserviceManager, 'findOne').returns($getMicroserviceResponse); + $sandbox.stub(StraceDiagnosticManager, 'findOne').returns($findStraceResponse); + $sandbox.stub(Config, 'get').returns($configGetResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(data, Validator.schemas.straceGetData); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls MicroserviceManager#findOne() with correct args', async () => { + await $subject; + const microserviceWhere = isCLI + ? {uuid: uuid} + : {uuid: uuid, userId: user.id}; + expect(MicroserviceManager.findOne).to.have.been.calledWith(microserviceWhere, transaction); + }); + + + context('when MicroserviceManager#findOne() fails', () => { + def('getMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when MicroserviceManager#findOne() succeeds', () => { + it('calls StraceDiagnosticManager#findOne() with correct args', async () => { + await $subject; + expect(StraceDiagnosticManager.findOne).to.have.been.calledWith({ + microserviceUuid: uuid + }, transaction); + }); + + context('when StraceDiagnosticManager#findOne() fails', () => { + def('findStraceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when StraceDiagnosticManager#findOne() succeeds', () => { + it('calls Config#get() with correct args', async () => { + await $subject; + expect(Config.get).to.have.been.calledWith('Diagnostics:DiagnosticDir'); + }); + + context('when Config#get() fails', () => { + def('configGetResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.eventually.have.property('data') + }) + }); + + context('when Config#get() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('data') + }) + }) + }) + }) + }) + }); + + // TODO handle FTP stuff + // describe('.postMicroserviceStraceDatatoFtp()', () => { + // const transaction = {}; + // const error = 'Error!'; + // + // const user = { + // id: 15 + // }; + // + // const uuid = 'testUuid'; + // + // const data = { + // ftpHost: 'testHost', + // ftpPort: 5555, + // ftpUser: 'testUser', + // ftpPass: 'testPass', + // ftpDestDir: 'testDir' + // }; + // + // const microservice = { + // iofogUuid: 'testIoFogUuid' + // }; + // + // def('subject', () => $subject.postMicroserviceStraceDatatoFtp(uuid, data, user, isCLI, transaction)); + // def('validatorResponse', () => Promise.resolve(true)); + // def('getMicroserviceResponse', () => Promise.resolve(microservice)); + // def('findStraceResponse', () => Promise.resolve({})); + // def('configGetResponse', () => Promise.resolve()); + // + // + // beforeEach(() => { + // $sandbox.stub(Validator, 'validate').returns($validatorResponse); + // $sandbox.stub(MicroserviceManager, 'findOne').returns($getMicroserviceResponse); + // $sandbox.stub(StraceDiagnosticManager, 'findOne').returns($findStraceResponse); + // $sandbox.stub(Config, 'get').returns($configGetResponse); + // }); + // + // it('calls Validator#validate() with correct args', async () => { + // await $subject; + // expect(Validator.validate).to.have.been.calledWith(data, Validator.schemas.stracePostToFtp); + // }); + // + // context('when Validator#validate() fails', () => { + // def('validatorResponse', () => Promise.reject(error)); + // + // it(`fails with ${error}`, () => { + // return expect($subject).to.be.rejectedWith(error) + // }) + // }); + // + // context('when Validator#validate() succeeds', () => { + // it('calls MicroserviceManager#findOne() with correct args', async () => { + // await $subject; + // const microserviceWhere = isCLI + // ? {uuid: uuid} + // : {uuid: uuid, userId: user.id}; + // expect(MicroserviceManager.findOne).to.have.been.calledWith(microserviceWhere, transaction); + // }); + // + // + // context('when MicroserviceManager#findOne() fails', () => { + // def('getMicroserviceResponse', () => Promise.reject(error)); + // + // it(`fails with ${error}`, () => { + // return expect($subject).to.be.rejectedWith(error) + // }) + // }); + // + // context('when MicroserviceManager#findOne() succeeds', () => { + // it('calls StraceDiagnosticManager#findOne() with correct args', async () => { + // await $subject; + // expect(StraceDiagnosticManager.findOne).to.have.been.calledWith({ + // microserviceUuid: uuid + // }, transaction); + // }); + // + // context('when StraceDiagnosticManager#findOne() fails', () => { + // def('findStraceResponse', () => Promise.reject(error)); + // + // it(`fails with ${error}`, () => { + // return expect($subject).to.be.rejectedWith(error) + // }) + // }); + // + // context('when StraceDiagnosticManager#findOne() succeeds', () => { + // it('calls Config#get() with correct args', async () => { + // await $subject; + // expect(Config.get).to.have.been.calledWith('Diagnostics:DiagnosticDir'); + // }); + // + // context('when Config#get() fails', () => { + // def('configGetResponse', () => error); + // + // it(`fails with ${error}`, () => { + // return expect($subject).to.be.eventually.have.property('data') + // }) + // }); + // + // context('when Config#get() succeeds', () => { + // it('fulfills the promise', () => { + // return expect($subject).to.eventually.have.property('data') + // }) + // }) + // }) + // }) + // }) + // }); + + describe('.postMicroserviceImageSnapshotCreate()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = 'user!'; + + const microserviceUuid = 'testUuid'; + + const microserviceToUpdate = { + imageSnapshot: 'get_image' + }; + + const microservice = { + iofogUuid: 'testIoFogUuid', + uuid: 'testMicroserviceUuid' + }; + + + def('subject', () => $subject.postMicroserviceImageSnapshotCreate(microserviceUuid, user, isCLI, transaction)); + def('findMicroserviceResponse', () => Promise.resolve(microservice)); + def('updateMicroserviceResponse', () => Promise.resolve()); + def('updateChangeTrackingResponse', () => Promise.resolve()); + + + beforeEach(() => { + $sandbox.stub(MicroserviceManager, 'findOneWithDependencies').returns($findMicroserviceResponse); + $sandbox.stub(MicroserviceManager, 'update').returns($updateMicroserviceResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + }); + + it('calls MicroserviceManager#findOneWithDependencies() with correct args', async () => { + await $subject; + const where = isCLI ? + { + uuid: microserviceUuid + } + : + { + uuid: microserviceUuid, + userId: user.id + }; + expect(MicroserviceManager.findOneWithDependencies).to.have.been.calledWith(where, {}, transaction); + }); + + context('when MicroserviceManager#findOneWithDependencies() fails', () => { + def('findMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when MicroserviceManager#findOneWithDependencies() succeeds', () => { + it('calls MicroserviceManager#update() with correct args', async () => { + await $subject; + expect(MicroserviceManager.update).to.have.been.calledWith({ + uuid: microservice.uuid + }, microserviceToUpdate, transaction); + }); + + context('when MicroserviceManager#update() fails', () => { + def('updateMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when MicroserviceManager#update() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + expect(ChangeTrackingService.update).to.have.been.calledWith(microservice.iofogUuid, + ChangeTrackingService.events.imageSnapshot, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined) + }) + }) + }) + }) + }); + + describe('.getMicroserviceImageSnapshot()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = 'user!'; + + const microserviceUuid = 'testUuid'; + + const microserviceToUpdate = { + imageSnapshot: '' + }; + + const microservice = { + iofogUuid: 'testIoFogUuid', + uuid: 'testMicroserviceUuid', + imageSnapshot: 'testImagePath' + }; + + + def('subject', () => $subject.getMicroserviceImageSnapshot(microserviceUuid, user, isCLI, transaction)); + def('findMicroserviceResponse', () => Promise.resolve(microservice)); + def('updateMicroserviceResponse', () => Promise.resolve()); + + + beforeEach(() => { + $sandbox.stub(MicroserviceManager, 'findOneWithDependencies').returns($findMicroserviceResponse); + $sandbox.stub(MicroserviceManager, 'update').returns($updateMicroserviceResponse); + }); + + it('calls MicroserviceManager#findOneWithDependencies() with correct args', async () => { + await $subject; + const where = isCLI ? + { + uuid: microserviceUuid + } + : + { + uuid: microserviceUuid, + userId: user.id + }; + expect(MicroserviceManager.findOneWithDependencies).to.have.been.calledWith(where, {}, transaction); + }); + + context('when MicroserviceManager#findOneWithDependencies() fails', () => { + def('findMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when MicroserviceManager#findOneWithDependencies() succeeds', () => { + it('calls MicroserviceManager#update() with correct args', async () => { + await $subject; + expect(MicroserviceManager.update).to.have.been.calledWith({ + uuid: microservice.uuid + }, microserviceToUpdate, transaction); + }); + + context('when MicroserviceManager#update() fails', () => { + def('updateMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when MicroserviceManager#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(microservice.imageSnapshot) + }) + }) + }) + }); + + +}); \ No newline at end of file diff --git a/test/src/services/email-activation-code-service.test.js b/test/src/services/email-activation-code-service.test.js new file mode 100644 index 000000000..862007ae5 --- /dev/null +++ b/test/src/services/email-activation-code-service.test.js @@ -0,0 +1,179 @@ +const {expect} = require('chai'); +const sinon = require('sinon'); + +const EmailActivationCodeManager = require('../../../src/sequelize/managers/email-activation-code-manager'); +const EmailActivationCodeService = require('../../../src/services/email-activation-code-service'); +const AppHelper = require('../../../src/helpers/app-helper'); +const ErrorMessages = require('../../../src/helpers/error-messages'); + + +describe('EmailActivationCode Service', () => { + def('subject', () => EmailActivationCodeService); + def('sandbox', () => sinon.createSandbox()); + + afterEach(() => $sandbox.restore()); + + describe('.generateActivationCode()', () => { + const transaction = {}; + const error = 'Error!'; + + const response = { + activationCode: "abcdefgwdwdwdwdwd", + expirationTime: new Date().getTime() + ((60 * 60 * 24 * 3) * 1000) + }; + + def('subject', () => $subject.generateActivationCode(transaction)); + def('generateStringResponse', () => response.activationCode); + def('findActivationCodeResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(AppHelper, 'generateRandomString').returns($generateStringResponse); + $sandbox.stub(EmailActivationCodeManager, 'getByActivationCode').returns($findActivationCodeResponse); + }); + + it('calls AppHelper#generateRandomString() with correct args', async () => { + await $subject; + expect(AppHelper.generateRandomString).to.have.been.calledWith(16); + }); + + context('when AppHelper#generateRandomString() fails', () => { + def('generateStringResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('activationCode') + }) + }); + + context('when AppHelper#generateRandomString() succeeds', () => { + it('calls EmailActivationCodeManager#getByActivationCode() with correct args', async () => { + await $subject; + expect(EmailActivationCodeManager.getByActivationCode).to.have.been.calledWith(response.activationCode, + transaction); + }); + + context('when EmailActivationCodeManager#getByActivationCode() fails', () => { + def('findActivationCodeResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when EmailActivationCodeManager#getByActivationCode() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('activationCode') && + expect($subject).to.eventually.have.property('expirationTime') + }) + }) + }) + }); + + describe('.saveActivationCode()', () => { + const transaction = {}; + const error = 'Error!'; + + const userId = 15; + + const activationCodeData = { + activationCode: "abcdefgwdwdwdwdwd", + expirationTime: new Date().getTime() + ((60 * 60 * 24 * 3) * 1000) + }; + + def('subject', () => $subject.saveActivationCode(userId, activationCodeData, transaction)); + def('createActivationCodeResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(EmailActivationCodeManager, 'createActivationCode').returns($createActivationCodeResponse); + }); + + it('calls EmailActivationCodeManager#createActivationCode() with correct args', async () => { + await $subject; + expect(EmailActivationCodeManager.createActivationCode).to.have.been.calledWith(userId, + activationCodeData.activationCode, activationCodeData.expirationTime, transaction); + }); + + context('when EmailActivationCodeManager#createActivationCode() fails', () => { + def('createActivationCodeResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(ErrorMessages.UNABLE_TO_CREATE_ACTIVATION_CODE); + }) + }); + + context('when EmailActivationCodeManager#createActivationCode() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.deep.equal(undefined) + }) + }) + }); + + describe('.verifyActivationCode()', () => { + const transaction = {}; + const error = 'Error!'; + + const activationCode = "abcdefgwdwdwdwdwd"; + + def('subject', () => $subject.verifyActivationCode(activationCode, transaction)); + def('verifyActivationCodeResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(EmailActivationCodeManager, 'verifyActivationCode').returns($verifyActivationCodeResponse); + }); + + it('calls EmailActivationCodeManager#verifyActivationCode() with correct args', async () => { + await $subject; + expect(EmailActivationCodeManager.verifyActivationCode).to.have.been.calledWith(activationCode, transaction); + }); + + context('when EmailActivationCodeManager#verifyActivationCode() fails', () => { + def('verifyActivationCodeResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(ErrorMessages.UNABLE_TO_GET_ACTIVATION_CODE); + }) + }); + + context('when EmailActivationCodeManager#verifyActivationCode() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.deep.equal(undefined) + }) + }) + }); + + describe('.deleteActivationCode()', () => { + const transaction = {}; + const error = 'Error!'; + + const activationCode = "abcdefgwdwdwdwdwd"; + + def('subject', () => $subject.deleteActivationCode(activationCode, transaction)); + def('deleteActivationCodeResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(EmailActivationCodeManager, 'delete').returns($deleteActivationCodeResponse); + }); + + it('calls EmailActivationCodeManager#delete() with correct args', async () => { + await $subject; + expect(EmailActivationCodeManager.delete).to.have.been.calledWith({ + activationCode: activationCode + }, transaction); + }); + + context('when EmailActivationCodeManager#delete() fails', () => { + def('deleteActivationCodeResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when EmailActivationCodeManager#delete() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.deep.equal(undefined) + }) + }) + }); + + +}); \ No newline at end of file diff --git a/test/src/services/flow-service.test.js b/test/src/services/flow-service.test.js new file mode 100644 index 000000000..d0045af4b --- /dev/null +++ b/test/src/services/flow-service.test.js @@ -0,0 +1,531 @@ +const {expect} = require('chai'); +const sinon = require('sinon'); + +const FlowManager = require('../../../src/sequelize/managers/flow-manager'); +const FlowService = require('../../../src/services/flow-service'); +const AppHelper = require('../../../src/helpers/app-helper'); +const Validator = require('../../../src/schemas'); +const ChangeTrackingService = require('../../../src/services/change-tracking-service'); +const Sequelize = require('sequelize'); +const Op = Sequelize.Op; +const ErrorMessages = require('../../../src/helpers/error-messages'); + +describe('Flow Service', () => { + def('subject', () => FlowService); + def('sandbox', () => sinon.createSandbox()); + + const isCLI = false; + + afterEach(() => $sandbox.restore()); + + describe('.createFlow()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const flowId = null; + + const flowData = { + name: 'testName', + description: 'testDescription', + isActivated: false + }; + + const flowToCreate = { + name: flowData.name, + description: flowData.description, + isActivated: flowData.isActivated, + userId: user.id + }; + + const response = { + id: 25 + }; + + def('subject', () => $subject.createFlow(flowData, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findFlowResponse', () => Promise.resolve()); + def('deleteUndefinedFieldsResponse', () => flowToCreate); + def('createFlowResponse', () => Promise.resolve(response)); + + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(FlowManager, 'findOne').returns($findFlowResponse); + $sandbox.stub(AppHelper, 'deleteUndefinedFields').returns($deleteUndefinedFieldsResponse); + $sandbox.stub(FlowManager, 'create').returns($createFlowResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(flowData, Validator.schemas.flowCreate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls FlowManager#findOne() with correct args', async () => { + await $subject; + const where = flowId + ? {name: flowData.name, id: {[Op.ne]: flowId, userId: user.id}} + : {name: flowData.name, userId: user.id}; + + expect(FlowManager.findOne).to.have.been.calledWith(where, transaction); + }); + + context('when FlowManager#findOne() fails', () => { + def('findFlowResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when FlowManager#findOne() succeeds', () => { + it('calls AppHelper#deleteUndefinedFields() with correct args', async () => { + await $subject; + + expect(AppHelper.deleteUndefinedFields).to.have.been.calledWith(flowToCreate); + }); + + context('when AppHelper#deleteUndefinedFields() fails', () => { + def('deleteUndefinedFieldsResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('id') + }) + }); + + context('when AppHelper#deleteUndefinedFields() succeeds', () => { + it('calls FlowManager#create() with correct args', async () => { + await $subject; + + expect(FlowManager.create).to.have.been.calledWith(flowToCreate); + }); + + context('when FlowManager#create() fails', () => { + def('createFlowResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('id') + }) + }); + + context('when FlowManager#create() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('id') + }) + }) + }) + }) + }) + }); + + describe('.deleteFlow()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const flowId = 75; + + const whereObj = { + id: flowId, + userId: user.id + }; + + const flowWithMicroservices = { + microservices: [ + { + iofogUuid: 15 + } + ] + }; + + def('subject', () => $subject.deleteFlow(flowId, user, isCLI, transaction)); + def('deleteUndefinedFieldsResponse', () => whereObj); + def('findFlowMicroservicesResponse', () => Promise.resolve(flowWithMicroservices)); + def('updateChangeTrackingResponse', () => Promise.resolve()); + def('deleteFlowResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(AppHelper, 'deleteUndefinedFields').returns($deleteUndefinedFieldsResponse); + $sandbox.stub(FlowManager, 'findFlowMicroservices').returns($findFlowMicroservicesResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + $sandbox.stub(FlowManager, 'delete').returns($deleteFlowResponse); + }); + + it('calls AppHelper#deleteUndefinedFields() with correct args', async () => { + await $subject; + expect(AppHelper.deleteUndefinedFields).to.have.been.calledWith(whereObj); + }); + + context('when AppHelper#deleteUndefinedFields() fails', () => { + def('deleteUndefinedFieldsResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + + context('when AppHelper#deleteUndefinedFields() succeeds', () => { + it('calls FlowManager#findFlowMicroservices() with correct args', async () => { + await $subject; + + expect(FlowManager.findFlowMicroservices).to.have.been.calledWith({ + id: flowId + }, transaction); + }); + + context('when FlowManager#findFlowMicroservices() fails', () => { + def('findFlowMicroservicesResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when FlowManager#findFlowMicroservices() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + + expect(ChangeTrackingService.update).to.have.been.calledWith(flowWithMicroservices.microservices[0].iofogUuid, + ChangeTrackingService.events.microserviceFull, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('calls FlowManager#delete() with correct args', async () => { + await $subject; + + expect(FlowManager.delete).to.have.been.calledWith(whereObj, transaction); + }); + + context('when FlowManager#delete() fails', () => { + def('deleteFlowResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when FlowManager#delete() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined) + }) + }) + }) + }) + }) + }); + + + describe('.updateFlow()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const flowId = 75; + + const oldFlowData = { + name: 'testName', + description: 'testDescription', + isActivated: true + }; + + const flowData = { + name: 'testName', + description: 'testDescription', + isActivated: false + }; + + const flowWithMicroservices = { + microservices: [ + { + iofogUuid: 15 + } + ] + }; + + def('subject', () => $subject.updateFlow(flowData, flowId, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findExcludedFlowResponse', () => Promise.resolve(oldFlowData)); + def('findFlowResponse', () => Promise.resolve()); + def('deleteUndefinedFieldsResponse', () => flowData); + def('updateFlowResponse', () => Promise.resolve()); + def('findFlowMicroservicesResponse', () => Promise.resolve(flowWithMicroservices)); + def('updateChangeTrackingResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(FlowManager, 'findOneExcludeFields').returns($findExcludedFlowResponse); + $sandbox.stub(FlowManager, 'findOne').returns($findFlowResponse); + $sandbox.stub(AppHelper, 'deleteUndefinedFields').returns($deleteUndefinedFieldsResponse); + $sandbox.stub(FlowManager, 'update').returns($updateFlowResponse); + $sandbox.stub(FlowManager, 'findFlowMicroservices').returns($findFlowMicroservicesResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(flowData, Validator.schemas.flowUpdate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls FlowManager#findOneExcludeFields() with correct args', async () => { + await $subject; + + const where = isCLI + ? {id: flowId} + : {id: flowId, userId: user.id}; + expect(FlowManager.findOneExcludeFields).to.have.been.calledWith(where, transaction); + }); + + context('when FlowManager#findOneExcludeFields() fails', () => { + def('findExcludedFlowResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when FlowManager#findOneExcludeFields() succeeds', () => { + it('calls FlowManager#findOne() with correct args', async () => { + await $subject; + + const where = flowId + ? {name: flowData.name, id: {[Op.ne]: flowId, userId: user.id}} + : {name: flowData.name, userId: user.id}; + expect(FlowManager.findOne).to.have.been.calledWith(where, transaction); + }); + + context('when FlowManager#findOne() fails', () => { + def('findFlowResponse', () => Promise.reject(AppHelper.formatMessage(ErrorMessages.DUPLICATE_NAME, + flowData.name))); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(AppHelper.formatMessage(ErrorMessages.DUPLICATE_NAME, + flowData.name)); + }) + }); + + context('when FlowManager#findOne() succeeds', () => { + it('calls AppHelper#deleteUndefinedFields() with correct args', async () => { + await $subject; + + expect(AppHelper.deleteUndefinedFields).to.have.been.calledWith(flowData); + }); + + context('when AppHelper#deleteUndefinedFields() fails', () => { + def('deleteUndefinedFieldsResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + + context('when AppHelper#deleteUndefinedFields() succeeds', () => { + it('calls FlowManager#update() with correct args', async () => { + await $subject; + + const where = isCLI + ? {id: flowId} + : {id: flowId, userId: user.id}; + expect(FlowManager.update).to.have.been.calledWith(where, flowData, transaction); + }); + + context('when FlowManager#update() fails', () => { + def('updateFlowResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when FlowManager#update() succeeds', () => { + it('calls FlowManager#findFlowMicroservices() with correct args', async () => { + await $subject; + + expect(FlowManager.findFlowMicroservices).to.have.been.calledWith({ + id: flowId + }, transaction); + }); + + context('when FlowManager#findFlowMicroservices() fails', () => { + def('findFlowMicroservicesResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when FlowManager#findFlowMicroservices() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + + expect(ChangeTrackingService.update).to.have.been.calledWith(flowWithMicroservices.microservices[0].iofogUuid, + ChangeTrackingService.events.microserviceFull, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined) + }) + }) + }) + }) + }) + }) + }) + }) + }); + + describe('.getUserFlows()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const flow = { + userId: user.id + }; + + def('subject', () => $subject.getUserFlows(user, isCLI, transaction)); + def('findExcludedFlowResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(FlowManager, 'findAllExcludeFields').returns($findExcludedFlowResponse); + }); + + it('calls FlowManager#findAllExcludeFields() with correct args', async () => { + await $subject; + expect(FlowManager.findAllExcludeFields).to.have.been.calledWith(flow, transaction); + }); + + context('when FlowManager#findAllExcludeFields() fails', () => { + def('findExcludedFlowResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when FlowManager#findAllExcludeFields() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('flows'); + }) + }) + }); + + + describe('.getAllFlows()', () => { + const transaction = {}; + const error = 'Error!'; + + def('subject', () => $subject.getAllFlows(isCLI, transaction)); + def('findAllFlowsResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(FlowManager, 'findAll').returns($findAllFlowsResponse); + }); + + it('calls FlowManager#findAll() with correct args', async () => { + await $subject; + expect(FlowManager.findAll).to.have.been.calledWith({}, transaction); + }); + + context('when FlowManager#findAll() fails', () => { + def('findAllFlowsResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when FlowManager#findAll() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('flows'); + }) + }) + }); + + describe('.getFlow()', () => { + const transaction = {}; + const error = 'Error!'; + + const flowId = 75; + + const user = { + id: 15 + }; + + def('subject', () => $subject.getFlow(flowId, user, isCLI, transaction)); + def('findFlowResponse', () => Promise.resolve({})); + + beforeEach(() => { + $sandbox.stub(FlowManager, 'findOneExcludeFields').returns($findFlowResponse); + }); + + it('calls FlowManager#findOneExcludeFields() with correct args', async () => { + await $subject; + const where = isCLI + ? {id: flowId} + : {id: flowId, userId: user.id}; + expect(FlowManager.findOneExcludeFields).to.have.been.calledWith(where, transaction); + }); + + context('when FlowManager#findOneExcludeFields() fails', () => { + def('findFlowResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when FlowManager#findOneExcludeFields() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.deep.equal({}); + }) + }) + }); + +}); \ No newline at end of file diff --git a/test/src/services/iofog-service.test.js b/test/src/services/iofog-service.test.js new file mode 100644 index 000000000..485053a26 --- /dev/null +++ b/test/src/services/iofog-service.test.js @@ -0,0 +1,1708 @@ +const {expect} = require('chai'); +const sinon = require('sinon'); + +const ioFogManager = require('../../../src/sequelize/managers/iofog-manager'); +const ioFogService = require('../../../src/services/iofog-service'); +const AppHelper = require('../../../src/helpers/app-helper'); +const Validator = require('../../../src/schemas'); +const ChangeTrackingService = require('../../../src/services/change-tracking-service'); +const CatalogService = require('../../../src/services/catalog-service'); +const MicroserviceManager = require('../../../src/sequelize/managers/microservice-manager'); +const ioFogProvisionKeyManager = require('../../../src/sequelize/managers/iofog-provision-key-manager'); +const ioFogVersionCommandManager = require('../../../src/sequelize/managers/iofog-version-command-manager'); +const HWInfoManager = require('../../../src/sequelize/managers/hw-info-manager'); +const USBInfoManager = require('../../../src/sequelize/managers/usb-info-manager'); + +describe('ioFog Service', () => { + def('subject', () => ioFogService); + def('sandbox', () => sinon.createSandbox()); + + const isCLI = false; + + afterEach(() => $sandbox.restore()); + + describe('.createFog()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const date = 155555555; + + const uuid = 'testUuid'; + const uuid2 = 'testUuid2'; + const uuid3 = 'testUuid3'; + + const fogData = { + name: 'testName', + location: 'testLocation', + latitude: 45, + longitude: 46, + description: 'testDescription', + dockerUrl: 'testDockerUrl', + diskLimit: 15, + diskDirectory: 'testDirectory', + memoryLimit: 55, + cpuLimit: 56, + logLimit: 57, + logDirectory: 'testLogDirectory', + logFileCount: 23, + statusFrequency: 24, + changeFrequency: 25, + deviceScanFrequency: 26, + bluetoothEnabled: true, + watchdogEnabled: false, + abstractedHardwareEnabled: true, + fogType: 1 + }; + + const createFogData = { + uuid: uuid, + name: fogData.name, + location: fogData.location, + latitude: fogData.latitude, + longitude: fogData.longitude, + gpsMode: fogData.latitude || fogData.longitude ? 'manual' : undefined, + description: fogData.description, + dockerUrl: fogData.dockerUrl, + diskLimit: fogData.diskLimit, + diskDirectory: fogData.diskDirectory, + memoryLimit: fogData.memoryLimit, + cpuLimit: fogData.cpuLimit, + logLimit: fogData.logLimit, + logDirectory: fogData.logDirectory, + logFileCount: fogData.logFileCount, + statusFrequency: fogData.statusFrequency, + changeFrequency: fogData.changeFrequency, + deviceScanFrequency: fogData.deviceScanFrequency, + bluetoothEnabled: fogData.bluetoothEnabled, + watchdogEnabled: fogData.watchdogEnabled, + abstractedHardwareEnabled: fogData.abstractedHardwareEnabled, + fogTypeId: fogData.fogType, + userId: user.id + }; + + const halItem = { + id: 10 + }; + + const oldFog = null; + const halMicroserviceData = { + uuid: uuid2, + name: `Hal for Fog ${createFogData.uuid}`, + config: '{}', + catalogItemId: halItem.id, + iofogUuid: createFogData.uuid, + rootHostAccess: true, + logSize: 50, + userId: oldFog ? oldFog.userId : user.id, + configLastUpdated: date + }; + + + const bluetoothItem = { + id: 10 + }; + const bluetoothMicroserviceData = { + uuid: uuid3, + name: `Bluetooth for Fog ${createFogData.uuid}`, + config: '{}', + catalogItemId: bluetoothItem.id, + iofogUuid: createFogData.uuid, + rootHostAccess: true, + logSize: 50, + userId: oldFog ? oldFog.userId : user.id, + configLastUpdated: date + }; + + + const response = { + uuid: uuid + }; + + def('subject', () => $subject.createFog(fogData, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('generateRandomStringResponse', () => uuid); + def('generateRandomStringResponse2', () => uuid2); + def('generateRandomStringResponse3', () => uuid3); + def('deleteUndefinedFieldsResponse', () => createFogData); + def('createIoFogResponse', () => Promise.resolve(response)); + def('createChangeTrackingResponse', () => Promise.resolve()); + def('getHalCatalogItemResponse', () => Promise.resolve(halItem)); + def('createMicroserviceResponse', () => Promise.resolve()); + def('createMicroserviceResponse2', () => Promise.resolve()); + def('getBluetoothCatalogItemResponse', () => Promise.resolve(bluetoothItem)); + def('updateChangeTrackingResponse', () => Promise.resolve()); + + def('dateResponse', () => date); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(AppHelper, 'generateRandomString') + .onFirstCall().returns($generateRandomStringResponse) + .onSecondCall().returns($generateRandomStringResponse2) + .onThirdCall().returns($generateRandomStringResponse3); + $sandbox.stub(AppHelper, 'deleteUndefinedFields').returns($deleteUndefinedFieldsResponse); + $sandbox.stub(ioFogManager, 'create').returns($createIoFogResponse); + $sandbox.stub(ChangeTrackingService, 'create').returns($createChangeTrackingResponse); + $sandbox.stub(CatalogService, 'getHalCatalogItem').returns($getHalCatalogItemResponse); + $sandbox.stub(MicroserviceManager, 'create') + .onFirstCall().returns($createMicroserviceResponse) + .onSecondCall().returns($createMicroserviceResponse2); + $sandbox.stub(CatalogService, 'getBluetoothCatalogItem').returns($getBluetoothCatalogItemResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + + $sandbox.stub(Date, 'now').returns($dateResponse); + + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(fogData, Validator.schemas.iofogCreate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls AppHelper#generateRandomString() with correct args', async () => { + await $subject; + expect(AppHelper.generateRandomString).to.have.been.calledWith(32); + }); + + context('when AppHelper#generateRandomString() fails', () => { + def('generateRandomStringResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('uuid'); + }) + }); + + context('when AppHelper#generateRandomString() succeeds', () => { + it('calls AppHelper#deleteUndefinedFields() with correct args', async () => { + await $subject; + + expect(AppHelper.deleteUndefinedFields).to.have.been.calledWith(createFogData); + }); + + context('when AppHelper#deleteUndefinedFields() fails', () => { + def('deleteUndefinedFieldsResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('uuid') + }) + }); + + context('when AppHelper#deleteUndefinedFields() succeeds', () => { + it('calls ioFogManager#create() with correct args', async () => { + await $subject; + + expect(ioFogManager.create).to.have.been.calledWith(createFogData); + }); + + context('when ioFogManager#create() fails', () => { + def('createIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#create() succeeds', () => { + it('calls ChangeTrackingService#create() with correct args', async () => { + await $subject; + + expect(ChangeTrackingService.create).to.have.been.calledWith(uuid, transaction); + }); + + context('when ChangeTrackingService#create() fails', () => { + def('createIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#create() succeeds', () => { + it('calls CatalogService#getHalCatalogItem() with correct args', async () => { + await $subject; + + expect(CatalogService.getHalCatalogItem).to.have.been.calledWith(transaction); + }); + + context('when CatalogService#getHalCatalogItem() fails', () => { + def('getHalCatalogItemResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when CatalogService#getHalCatalogItem() succeeds', () => { + it('calls AppHelper#generateRandomString() with correct args', async () => { + await $subject; + + expect(AppHelper.generateRandomString).to.have.been.calledWith(32); + }); + + context('when AppHelper#generateRandomString() fails', () => { + def('generateRandomStringResponse2', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('uuid'); + }) + }); + + context('when AppHelper#generateRandomString() succeeds', () => { + it('calls MicroserviceManager#create() with correct args', async () => { + await $subject; + + expect(MicroserviceManager.create).to.have.been.calledWith(halMicroserviceData, transaction); + }); + + context('when MicroserviceManager#create() fails', () => { + def('createMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#create() succeeds', () => { + it('calls CatalogService#getBluetoothCatalogItem() with correct args', async () => { + await $subject; + + expect(CatalogService.getBluetoothCatalogItem).to.have.been.calledWith(transaction); + }); + + context('when CatalogService#getBluetoothCatalogItem() fails', () => { + def('getBluetoothCatalogItemResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when CatalogService#getBluetoothCatalogItem() succeeds', () => { + it('calls AppHelper#generateRandomString() with correct args', async () => { + await $subject; + + expect(AppHelper.generateRandomString).to.have.been.calledWith(32); + }); + + context('when AppHelper#generateRandomString() fails', () => { + def('generateRandomStringResponse3', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('uuid'); + }) + }); + + context('when AppHelper#generateRandomString() succeeds', () => { + it('calls MicroserviceManager#create() with correct args', async () => { + await $subject; + + expect(MicroserviceManager.create).to.have.been.calledWith(bluetoothMicroserviceData, transaction); + }); + + context('when MicroserviceManager#create() fails', () => { + def('createMicroserviceResponse2', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#create() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + + expect(ChangeTrackingService.update).to.have.been.calledWith(createFogData.uuid, + ChangeTrackingService.events.microserviceCommon, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('uuid') + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }); + + describe('.updateFog()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const date = 155555555; + + const uuid = 'testUuid'; + const uuid2 = 'testUuid2'; + const uuid3 = 'testUuid3'; + + const fogData = { + uuid: uuid, + name: 'testName', + location: 'testLocation', + latitude: 45, + longitude: 46, + description: 'testDescription', + dockerUrl: 'testDockerUrl', + diskLimit: 15, + diskDirectory: 'testDirectory', + memoryLimit: 55, + cpuLimit: 56, + logLimit: 57, + logDirectory: 'testLogDirectory', + logFileCount: 23, + statusFrequency: 24, + changeFrequency: 25, + deviceScanFrequency: 26, + bluetoothEnabled: true, + watchdogEnabled: false, + abstractedHardwareEnabled: true, + fogType: 1 + }; + + const oldFog = { + uuid: uuid2, + name: 'testName', + location: 'testLocation', + latitude: 45, + longitude: 46, + description: 'testDescription', + dockerUrl: 'testDockerUrl', + diskLimit: 15, + diskDirectory: 'testDirectory', + memoryLimit: 55, + cpuLimit: 56, + logLimit: 57, + logDirectory: 'testLogDirectory', + logFileCount: 23, + statusFrequency: 24, + changeFrequency: 25, + deviceScanFrequency: 26, + bluetoothEnabled: false, + watchdogEnabled: false, + abstractedHardwareEnabled: false, + fogType: 1 + }; + + const queryFogData = isCLI + ? {uuid: fogData.uuid} + : {uuid: fogData.uuid, userId: user.id}; + + let updateFogData = { + name: fogData.name, + location: fogData.location, + latitude: fogData.latitude, + longitude: fogData.longitude, + gpsMode: fogData.latitude || fogData.longitude ? 'manual' : undefined, + description: fogData.description, + dockerUrl: fogData.dockerUrl, + diskLimit: fogData.diskLimit, + diskDirectory: fogData.diskDirectory, + memoryLimit: fogData.memoryLimit, + cpuLimit: fogData.cpuLimit, + logLimit: fogData.logLimit, + logDirectory: fogData.logDirectory, + logFileCount: fogData.logFileCount, + statusFrequency: fogData.statusFrequency, + changeFrequency: fogData.changeFrequency, + deviceScanFrequency: fogData.deviceScanFrequency, + bluetoothEnabled: fogData.bluetoothEnabled, + watchdogEnabled: fogData.watchdogEnabled, + abstractedHardwareEnabled: fogData.abstractedHardwareEnabled, + fogTypeId: fogData.fogType, + }; + + const halItem = { + id: 10 + }; + const halMicroserviceData = { + uuid: uuid2, + name: `Hal for Fog ${fogData.uuid}`, + config: '{}', + catalogItemId: halItem.id, + iofogUuid: fogData.uuid, + rootHostAccess: true, + logSize: 50, + userId: oldFog ? oldFog.userId : user.id, + configLastUpdated: date + }; + + + const bluetoothItem = { + id: 10 + }; + const bluetoothMicroserviceData = { + uuid: uuid3, + name: `Bluetooth for Fog ${fogData.uuid}`, + config: '{}', + catalogItemId: bluetoothItem.id, + iofogUuid: fogData.uuid, + rootHostAccess: true, + logSize: 50, + userId: oldFog ? oldFog.userId : user.id, + configLastUpdated: date + }; + + def('subject', () => $subject.updateFog(fogData, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('deleteUndefinedFieldsResponse', () => updateFogData); + def('findIoFogResponse', () => Promise.resolve(oldFog)); + def('updateIoFogResponse', () => Promise.resolve()); + def('updateChangeTrackingResponse', () => Promise.resolve()); + def('updateChangeTrackingResponse2', () => Promise.resolve()); + def('getHalCatalogItemResponse', () => Promise.resolve(halItem)); + def('generateRandomStringResponse', () => uuid2); + def('generateRandomStringResponse2', () => uuid3); + def('createMicroserviceResponse', () => Promise.resolve()); + def('createMicroserviceResponse2', () => Promise.resolve()); + def('getBluetoothCatalogItemResponse', () => Promise.resolve(bluetoothItem)); + + def('dateResponse', () => date); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(AppHelper, 'deleteUndefinedFields').returns($deleteUndefinedFieldsResponse); + $sandbox.stub(ioFogManager, 'findOne').returns($findIoFogResponse); + $sandbox.stub(ioFogManager, 'update').returns($updateIoFogResponse); + $sandbox.stub(ChangeTrackingService, 'update') + .onFirstCall().returns($updateChangeTrackingResponse) + .onSecondCall().returns($updateChangeTrackingResponse2); + $sandbox.stub(CatalogService, 'getHalCatalogItem').returns($getHalCatalogItemResponse); + $sandbox.stub(AppHelper, 'generateRandomString') + .onFirstCall().returns($generateRandomStringResponse) + .onSecondCall().returns($generateRandomStringResponse2); + $sandbox.stub(MicroserviceManager, 'create') + .onFirstCall().returns($createMicroserviceResponse) + .onSecondCall().returns($createMicroserviceResponse2); + $sandbox.stub(CatalogService, 'getBluetoothCatalogItem').returns($getBluetoothCatalogItemResponse); + + $sandbox.stub(Date, 'now').returns($dateResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(fogData, Validator.schemas.iofogUpdate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls AppHelper#deleteUndefinedFields() with correct args', async () => { + await $subject; + + expect(AppHelper.deleteUndefinedFields).to.have.been.calledWith(updateFogData); + }); + + context('when AppHelper#deleteUndefinedFields() fails', () => { + def('deleteUndefinedFieldsResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + + context('when AppHelper#deleteUndefinedFields() succeeds', () => { + it('calls ioFogManager#findOne() with correct args', async () => { + await $subject; + + expect(ioFogManager.findOne).to.have.been.calledWith(queryFogData, transaction); + }); + + context('when ioFogManager#findOne() fails', () => { + def('findIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#findOne() succeeds', () => { + it('calls ioFogManager#update() with correct args', async () => { + await $subject; + + expect(ioFogManager.update).to.have.been.calledWith(queryFogData, + updateFogData, transaction); + }); + + context('when ioFogManager#update() fails', () => { + def('updateIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#update() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + + expect(ChangeTrackingService.update).to.have.been.calledWith(uuid, + ChangeTrackingService.events.config, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('calls CatalogService#getHalCatalogItem() with correct args', async () => { + await $subject; + + expect(CatalogService.getHalCatalogItem).to.have.been.calledWith(transaction); + }); + + context('when CatalogService#getHalCatalogItem() fails', () => { + def('getHalCatalogItemResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when CatalogService#getHalCatalogItem() succeeds', () => { + it('calls AppHelper#generateRandomString() with correct args', async () => { + await $subject; + + expect(AppHelper.generateRandomString).to.have.been.calledWith(32); + }); + + context('when AppHelper#generateRandomString() fails', () => { + def('generateRandomStringResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + + context('when AppHelper#generateRandomString() succeeds', () => { + it('calls MicroserviceManager#create() with correct args', async () => { + await $subject; + + expect(MicroserviceManager.create).to.have.been.calledWith(halMicroserviceData, transaction); + }); + + context('when MicroserviceManager#create() fails', () => { + def('createMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#create() succeeds', () => { + it('calls CatalogService#getBluetoothCatalogItem() with correct args', async () => { + await $subject; + + expect(CatalogService.getBluetoothCatalogItem).to.have.been.calledWith(transaction); + }); + + context('when CatalogService#getBluetoothCatalogItem() fails', () => { + def('getBluetoothCatalogItemResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when CatalogService#getBluetoothCatalogItem() succeeds', () => { + it('calls AppHelper#generateRandomString() with correct args', async () => { + await $subject; + + expect(AppHelper.generateRandomString).to.have.been.calledWith(32); + }); + + context('when AppHelper#generateRandomString() fails', () => { + def('generateRandomStringResponse2', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + + context('when AppHelper#generateRandomString() succeeds', () => { + it('calls MicroserviceManager#create() with correct args', async () => { + await $subject; + + expect(MicroserviceManager.create).to.have.been.calledWith(bluetoothMicroserviceData, transaction); + }); + + context('when MicroserviceManager#create() fails', () => { + def('createMicroserviceResponse2', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#create() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + + expect(ChangeTrackingService.update).to.have.been.calledWith(fogData.uuid, + ChangeTrackingService.events.microserviceCommon, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse2', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined); + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }); + + describe('.deleteFog()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const date = 155555555; + + const uuid = 'testUuid'; + + const fogData = { + uuid: uuid + }; + + const fog = { + uuid: uuid, + name: 'testName', + location: 'testLocation', + latitude: 45, + longitude: 46, + description: 'testDescription', + dockerUrl: 'testDockerUrl', + diskLimit: 15, + diskDirectory: 'testDirectory', + daemonStatus: 'RUNNING', + memoryLimit: 55, + cpuLimit: 56, + logLimit: 57, + logDirectory: 'testLogDirectory', + logFileCount: 23, + statusFrequency: 24, + changeFrequency: 25, + lastStatusTime: 1555, + ipAddress: 'testIpAddress', + deviceScanFrequency: 26, + bluetoothEnabled: false, + watchdogEnabled: false, + abstractedHardwareEnabled: false, + fogType: 1 + }; + + const queryFogData = isCLI + ? {uuid: fogData.uuid} + : {uuid: fogData.uuid, userId: user.id}; + + const toUpdate = { + daemonStatus: 'UNKNOWN', ipAddress: '0.0.0.0' + }; + + def('subject', () => $subject.deleteFog(fogData, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findIoFogResponse', () => Promise.resolve(fog)); + def('updateIoFogResponse', () => Promise.resolve()); + def('updateChangeTrackingResponse', () => Promise.resolve()); + + def('dateResponse', () => date); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(ioFogManager, 'findOne').returns($findIoFogResponse); + $sandbox.stub(ioFogManager, 'update').returns($updateIoFogResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + + $sandbox.stub(Date, 'now').returns($dateResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(fogData, Validator.schemas.iofogDelete); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls ioFogManager#findOne() with correct args', async () => { + await $subject; + + expect(ioFogManager.findOne).to.have.been.calledWith(queryFogData, transaction); + }); + + context('when ioFogManager#findOne() fails', () => { + def('findIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#findOne() succeeds', () => { + it('calls ioFogManager#update() with correct args', async () => { + await $subject; + const query = { + uuid: uuid + }; + expect(ioFogManager.update).to.have.been.calledWith(query, + toUpdate, transaction); + }); + + context('when ioFogManager#update() fails', () => { + def('updateIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#update() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + + expect(ChangeTrackingService.update).to.have.been.calledWith(uuid, ChangeTrackingService.events.deleteNode, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined); + }) + }) + }) + }) + }) + }); + + describe('.getFog()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const date = 155555555; + + const uuid = 'testUuid'; + + const fogData = { + uuid: uuid + }; + + const fog = { + uuid: uuid, + name: 'testName', + location: 'testLocation', + latitude: 45, + longitude: 46, + description: 'testDescription', + dockerUrl: 'testDockerUrl', + diskLimit: 15, + diskDirectory: 'testDirectory', + daemonStatus: 'RUNNING', + memoryLimit: 55, + cpuLimit: 56, + logLimit: 57, + logDirectory: 'testLogDirectory', + logFileCount: 23, + statusFrequency: 24, + changeFrequency: 25, + lastStatusTime: 1555, + ipAddress: 'testIpAddress', + deviceScanFrequency: 26, + bluetoothEnabled: false, + watchdogEnabled: false, + abstractedHardwareEnabled: false, + fogType: 1 + }; + + const queryFogData = isCLI + ? {uuid: fogData.uuid} + : {uuid: fogData.uuid, userId: user.id}; + + const toUpdate = { + daemonStatus: 'UNKNOWN', ipAddress: '0.0.0.0' + }; + + const fogResponse = { + uuid: fog.uuid, + name: fog.name, + location: fog.location, + gpsMode: fog.gpsMode, + latitude: fog.latitude, + longitude: fog.longitude, + description: fog.description, + lastActive: fog.lastActive, + daemonStatus: 'UNKNOWN', + daemonOperatingDuration: fog.daemonOperatingDuration, + daemonLastStart: fog.daemonLastStart, + memoryUsage: fog.memoryUsage, + diskUsage: fog.diskUsage, + cpuUsage: fog.cpuUsage, + memoryViolation: fog.memoryViolation, + diskViolation: fog.diskViolation, + cpuViolation: fog.cpuViolation, + catalogItemStatus: fog.catalogItemStatus, + repositoryCount: fog.repositoryCount, + repositoryStatus: fog.repositoryStatus, + systemTime: fog.systemTime, + lastStatusTime: fog.lastStatusTime, + ipAddress: '0.0.0.0', + processedMessages: fog.processedMessages, + catalogItemMessageCounts: fog.catalogItemMessageCounts, + messageSpeed: fog.messageSpeed, + lastCommandTime: fog.lastCommandTime, + networkInterface: fog.networkInterface, + dockerUrl: fog.dockerUrl, + diskLimit: fog.diskLimit, + diskDirectory: fog.diskDirectory, + memoryLimit: fog.memoryLimit, + cpuLimit: fog.cpuLimit, + logLimit: fog.logLimit, + logDirectory: fog.logDirectory, + bluetoothEnabled: fog.bluetoothEnabled, + abstractedHardwareEnabled: fog.abstractedHardwareEnabled, + logFileCount: fog.logFileCount, + version: fog.version, + isReadyToUpgrade: fog.isReadyToUpgrade, + isReadyToRollback: fog.isReadyToRollback, + statusFrequency: fog.statusFrequency, + changeFrequency: fog.changeFrequency, + deviceScanFrequency: fog.deviceScanFrequency, + tunnel: fog.tunnel, + watchdogEnabled: fog.watchdogEnabled, + fogTypeId: fog.fogTypeId, + userId: fog.userId + }; + + def('subject', () => $subject.getFog(fogData, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findIoFogResponse', () => Promise.resolve(fog)); + def('updateIoFogResponse', () => Promise.resolve()); + + def('dateResponse', () => date); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(ioFogManager, 'findOne').returns($findIoFogResponse); + $sandbox.stub(ioFogManager, 'update').returns($updateIoFogResponse); + + $sandbox.stub(Date, 'now').returns($dateResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(fogData, Validator.schemas.iofogGet); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls ioFogManager#findOne() with correct args', async () => { + await $subject; + + expect(ioFogManager.findOne).to.have.been.calledWith(queryFogData, transaction); + }); + + context('when ioFogManager#findOne() fails', () => { + def('findIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#findOne() succeeds', () => { + it('calls ioFogManager#update() with correct args', async () => { + await $subject; + const query = { + uuid: uuid + }; + expect(ioFogManager.update).to.have.been.calledWith(query, + toUpdate, transaction); + }); + + context('when ioFogManager#update() fails', () => { + def('updateIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.deep.equal(fogResponse); + }) + }) + }) + }) + }); + + describe('.getFogList()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const date = 155555555; + + const uuid = 'testUuid'; + + const fog = { + uuid: uuid, + name: 'testName', + location: 'testLocation', + latitude: 45, + longitude: 46, + description: 'testDescription', + dockerUrl: 'testDockerUrl', + diskLimit: 15, + diskDirectory: 'testDirectory', + daemonStatus: 'RUNNING', + memoryLimit: 55, + cpuLimit: 56, + logLimit: 57, + logDirectory: 'testLogDirectory', + logFileCount: 23, + statusFrequency: 24, + changeFrequency: 25, + lastStatusTime: 1555, + ipAddress: 'testIpAddress', + deviceScanFrequency: 26, + bluetoothEnabled: false, + watchdogEnabled: false, + abstractedHardwareEnabled: false, + fogType: 1 + }; + + const fogs = [fog]; + + const queryFogData = isCLI + ? {} + : {userId: user.id}; + + const toUpdate = { + daemonStatus: 'UNKNOWN', ipAddress: '0.0.0.0' + }; + + const filters = []; + + def('subject', () => $subject.getFogList(filters, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findAllIoFogResponse', () => Promise.resolve(fogs)); + def('updateIoFogResponse', () => Promise.resolve()); + + def('dateResponse', () => date); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(ioFogManager, 'findAll').returns($findAllIoFogResponse); + $sandbox.stub(ioFogManager, 'update').returns($updateIoFogResponse); + + $sandbox.stub(Date, 'now').returns($dateResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(filters, Validator.schemas.iofogFilters); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls ioFogManager#findAll() with correct args', async () => { + await $subject; + + expect(ioFogManager.findAll).to.have.been.calledWith(queryFogData, transaction); + }); + + context('when ioFogManager#findAll() fails', () => { + def('findAllIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#findAll() succeeds', () => { + it('calls ioFogManager#update() with correct args', async () => { + await $subject; + const query = { + uuid: uuid + }; + expect(ioFogManager.update).to.have.been.calledWith(query, + toUpdate, transaction); + }); + + context('when ioFogManager#update() fails', () => { + def('updateIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('fogs'); + }) + }) + }) + }) + }); + + describe('.generateProvisioningKey()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const uuid = 'testUuid'; + + const date = 155555555; + + const fogData = { + uuid: uuid + }; + + const queryFogData = isCLI + ? {uuid: fogData.uuid} + : {uuid: fogData.uuid, userId: user.id}; + + const provisionKey = 'tttttttt'; + const expirationTime = date + (20 * 60 * 1000); + + const newProvision = { + iofogUuid: fogData.uuid, + provisionKey: provisionKey, + expirationTime: expirationTime, + }; + + def('subject', () => $subject.generateProvisioningKey(fogData, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('generateRandomStringResponse', () => provisionKey); + def('findIoFogResponse', () => Promise.resolve({})); + def('updateOrCreateProvisionKeyResponse', () => Promise.resolve(newProvision)); + + def('dateResponse', () => date); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(AppHelper, 'generateRandomString').returns($generateRandomStringResponse); + $sandbox.stub(ioFogManager, 'findOne').returns($findIoFogResponse); + $sandbox.stub(ioFogProvisionKeyManager, 'updateOrCreate').returns($updateOrCreateProvisionKeyResponse); + + $sandbox.stub(Date.prototype, 'getTime').returns($dateResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(fogData, Validator.schemas.iofogGenerateProvision); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls AppHelper#generateRandomString() with correct args', async () => { + await $subject; + + expect(AppHelper.generateRandomString).to.have.been.calledWith(8); + }); + + context('when AppHelper#generateRandomString() fails', () => { + def('generateRandomStringResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('key'); + }) + }); + + context('when AppHelper#generateRandomString() succeeds', () => { + it('calls ioFogManager#findOne() with correct args', async () => { + await $subject; + expect(ioFogManager.findOne).to.have.been.calledWith(queryFogData, transaction); + }); + + context('when ioFogManager#findOne() fails', () => { + def('findIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#findOne() succeeds', () => { + it('calls ioFogProvisionKeyManager#updateOrCreate() with correct args', async () => { + await $subject; + expect(ioFogProvisionKeyManager.updateOrCreate).to.have.been.calledWith({ + iofogUuid: fogData.uuid + }, newProvision, transaction); + }); + + context('when ioFogProvisionKeyManager#updateOrCreate() fails', () => { + def('updateOrCreateProvisionKeyResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogProvisionKeyManager#updateOrCreate() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.deep.equal({ + key: provisionKey, + expirationTime: expirationTime + }) + }) + }) + }) + }) + }) + }); + + describe('.setFogVersionCommand()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const uuid = 'testUuid'; + + const date = 155555555; + + const fogVersionData = { + uuid: uuid, + versionCommand: 'upgrade' + }; + + const queryFogData = isCLI + ? {uuid: fogVersionData.uuid} + : {uuid: fogVersionData.uuid, userId: user.id}; + + const ioFog = { + uuid: uuid, + isReadyToUpgrade: true, + isReadyToRollback: true + }; + + const newVersionCommand = { + iofogUuid: fogVersionData.uuid, + versionCommand: fogVersionData.versionCommand + }; + + const provisionKey = 'tttttttt'; + const expirationTime = date + (20 * 60 * 1000); + + const newProvision = { + iofogUuid: uuid, + provisionKey: provisionKey, + expirationTime: expirationTime, + }; + + def('subject', () => $subject.setFogVersionCommand(fogVersionData, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findIoFogResponse', () => Promise.resolve(ioFog)); + def('generateRandomStringResponse', () => provisionKey); + def('updateOrCreateProvisionKeyResponse', () => Promise.resolve(newProvision)); + def('findIoFogVersionCommandResponse', () => Promise.resolve()); + def('updateChangeTrackingResponse', () => Promise.resolve()); + + def('dateResponse', () => date); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(ioFogManager, 'findOne').returns($findIoFogResponse); + $sandbox.stub(AppHelper, 'generateRandomString').returns($generateRandomStringResponse); + $sandbox.stub(ioFogProvisionKeyManager, 'updateOrCreate').returns($updateOrCreateProvisionKeyResponse); + $sandbox.stub(ioFogVersionCommandManager, 'updateOrCreate').returns($findIoFogVersionCommandResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + + $sandbox.stub(Date.prototype, 'getTime').returns($dateResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(fogVersionData, Validator.schemas.iofogSetVersionCommand); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls ioFogManager#findOne() with correct args', async () => { + await $subject; + expect(ioFogManager.findOne).to.have.been.calledWith(queryFogData, transaction); + }); + + context('when ioFogManager#findOne() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#findOne() succeeds', () => { + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith({ + uuid: fogVersionData.uuid + }, Validator.schemas.iofogGenerateProvision); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls AppHelper#generateRandomString() with correct args', async () => { + await $subject; + + expect(AppHelper.generateRandomString).to.have.been.calledWith(8); + }); + + context('when AppHelper#generateRandomString() fails', () => { + def('generateRandomStringResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + + context('when AppHelper#generateRandomString() succeeds', () => { + it('calls ioFogManager#findOne() with correct args', async () => { + await $subject; + expect(ioFogManager.findOne).to.have.been.calledWith(queryFogData, transaction); + }); + + context('when ioFogManager#findOne() fails', () => { + def('findIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#findOne() succeeds', () => { + it('calls ioFogProvisionKeyManager#updateOrCreate() with correct args', async () => { + await $subject; + expect(ioFogProvisionKeyManager.updateOrCreate).to.have.been.calledWith({ + iofogUuid: uuid + }, newProvision, transaction); + }); + + context('when ioFogProvisionKeyManager#updateOrCreate() fails', () => { + def('updateOrCreateProvisionKeyResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogProvisionKeyManager#updateOrCreate() succeeds', () => { + it('calls ioFogVersionCommandManager#updateOrCreate() with correct args', async () => { + await $subject; + expect(ioFogVersionCommandManager.updateOrCreate).to.have.been.calledWith({ + iofogUuid: fogVersionData.uuid + }, newVersionCommand, transaction); + }); + + context('when ioFogVersionCommandManager#updateOrCreate() fails', () => { + def('updateOrCreateProvisionKeyResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogVersionCommandManager#updateOrCreate() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + expect(ChangeTrackingService.update).to.have.been.calledWith(fogVersionData.uuid, + ChangeTrackingService.events.version, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateOrCreateProvisionKeyResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined); + }) + }) + }) + }) + }) + }) + }) + }) + }) + }); + + describe('.setFogRebootCommand()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const uuid = 'testUuid'; + + const date = 155555555; + + const fogData = { + uuid: uuid + }; + + const queryFogData = isCLI + ? {uuid: fogData.uuid} + : {uuid: fogData.uuid, userId: user.id}; + + def('subject', () => $subject.setFogRebootCommand(fogData, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findIoFogResponse', () => Promise.resolve({})); + def('updateChangeTrackingResponse', () => Promise.resolve()); + + def('dateResponse', () => date); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(ioFogManager, 'findOne').returns($findIoFogResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(fogData, Validator.schemas.iofogReboot); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls ioFogManager#findOne() with correct args', async () => { + await $subject; + expect(ioFogManager.findOne).to.have.been.calledWith(queryFogData, transaction); + }); + + context('when ioFogManager#findOne() fails', () => { + def('findIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#findOne() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + expect(ChangeTrackingService.update).to.have.been.calledWith(fogData.uuid, + ChangeTrackingService.events.reboot, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined); + }) + }) + }) + }) + }); + + describe('.getHalHardwareInfo()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const uuid = 'testUuid'; + + const date = 155555555; + + const uuidObj = { + uuid: uuid + }; + + def('subject', () => $subject.getHalHardwareInfo(uuidObj, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findIoFogResponse', () => Promise.resolve({})); + def('findHalHardwareResponse', () => Promise.resolve()); + + def('dateResponse', () => date); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(ioFogManager, 'findOne').returns($findIoFogResponse); + $sandbox.stub(HWInfoManager, 'findOne').returns($findHalHardwareResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(uuidObj, Validator.schemas.halGet); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls ioFogManager#findOne() with correct args', async () => { + await $subject; + expect(ioFogManager.findOne).to.have.been.calledWith({ + uuid: uuidObj.uuid + }, transaction); + }); + + context('when ioFogManager#findOne() fails', () => { + def('findIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#findOne() succeeds', () => { + it('calls HWInfoManager#findOne() with correct args', async () => { + await $subject; + expect(HWInfoManager.findOne).to.have.been.calledWith({ + iofogUuid: uuidObj.uuid + }, transaction); + }); + + context('when HWInfoManager#findOne() fails', () => { + def('findHalHardwareResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when HWInfoManager#findOne() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined); + }) + }) + }) + }) + }); + + describe('.getHalUsbInfo()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const uuid = 'testUuid'; + + const date = 155555555; + + const uuidObj = { + uuid: uuid + }; + + def('subject', () => $subject.getHalUsbInfo(uuidObj, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findIoFogResponse', () => Promise.resolve({})); + def('findHalUsbResponse', () => Promise.resolve()); + + def('dateResponse', () => date); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(ioFogManager, 'findOne').returns($findIoFogResponse); + $sandbox.stub(USBInfoManager, 'findOne').returns($findHalUsbResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(uuidObj, Validator.schemas.halGet); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls ioFogManager#findOne() with correct args', async () => { + await $subject; + expect(ioFogManager.findOne).to.have.been.calledWith({ + uuid: uuidObj.uuid + }, transaction); + }); + + context('when ioFogManager#findOne() fails', () => { + def('findIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#findOne() succeeds', () => { + it('calls USBInfoManager#findOne() with correct args', async () => { + await $subject; + expect(USBInfoManager.findOne).to.have.been.calledWith({ + iofogUuid: uuidObj.uuid + }, transaction); + }); + + context('when USBInfoManager#findOne() fails', () => { + def('findHalUsbResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when USBInfoManager#findOne() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined); + }) + }) + }) + }) + }); + + +}); \ No newline at end of file diff --git a/test/src/services/microservices-service.test.js b/test/src/services/microservices-service.test.js new file mode 100644 index 000000000..3b7941eae --- /dev/null +++ b/test/src/services/microservices-service.test.js @@ -0,0 +1,1334 @@ +const {expect} = require('chai'); +const sinon = require('sinon'); + +const MicroserviceManager = require('../../../src/sequelize/managers/microservice-manager'); +const MicroservicesService = require('../../../src/services/microservices-service'); +const AppHelper = require('../../../src/helpers/app-helper'); +const Validator = require('../../../src/schemas'); +const ChangeTrackingService = require('../../../src/services/change-tracking-service'); +const CatalogService = require('../../../src/services/catalog-service'); +const FlowService = require('../../../src/services/flow-service'); +const ioFogService = require('../../../src/services/iofog-service'); +const MicroservicePortManager = require('../../../src/sequelize/managers/microservice-port-manager'); +const VolumeMappingManager = require('../../../src/sequelize/managers/volume-mapping-manager'); +const MicroserviceStatusManager = require('../../../src/sequelize/managers/microservice-status-manager'); +const RoutingManager = require('../../../src/sequelize/managers/routing-manager'); +const Op = require('sequelize').Op; + +describe('Microservices Service', () => { + def('subject', () => MicroservicesService); + def('sandbox', () => sinon.createSandbox()); + + const isCLI = true; + + afterEach(() => $sandbox.restore()); + + describe('.listMicroservices()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const flowId = 10; + + const response = [ + { + uuid: 'testUuid' + } + ]; + + def('subject', () => $subject.listMicroservices(flowId, user, isCLI, transaction)); + def('findMicroservicesResponse', () => Promise.resolve(response)); + + beforeEach(() => { + $sandbox.stub(MicroserviceManager, 'findAllExcludeFields').returns($findMicroservicesResponse); + }); + + it('calls MicroserviceManager#findAllExcludeFields() with correct args', async () => { + await $subject; + const where = isCLI ? {delete: false} : {flowId: flowId, delete: false}; + + expect(MicroserviceManager.findAllExcludeFields).to.have.been.calledWith(where, transaction); + }); + + context('when MicroserviceManager#findAllExcludeFields() fails', () => { + def('findMicroservicesResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#findAllExcludeFields() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('microservices') + }) + }) + }); + + describe('.getMicroservice()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const microserviceUuid = 'testMicroserviceUuid'; + + const response = { + uuid: 'testUuid' + }; + + def('subject', () => $subject.getMicroservice(microserviceUuid, user, isCLI, transaction)); + def('findMicroserviceResponse', () => Promise.resolve(response)); + + beforeEach(() => { + $sandbox.stub(MicroserviceManager, 'findOneExcludeFields').returns($findMicroserviceResponse); + }); + + it('calls MicroserviceManager#findOneExcludeFields() with correct args', async () => { + await $subject; + expect(MicroserviceManager.findOneExcludeFields).to.have.been.calledWith({ + uuid: microserviceUuid, delete: false + }, transaction); + }); + + context('when MicroserviceManager#findOneExcludeFields() fails', () => { + def('findMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#findOneExcludeFields() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('uuid') + }) + }) + }); + + describe('.createMicroservice()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const microserviceData = { + "name": "name2", + "config": "string", + "catalogItemId": 15, + "flowId": 16, + "iofogUuid": 'testIofogUuid', + "rootHostAccess": true, + "logSize": 0, + "volumeMappings": [ + { + "hostDestination": "/var/dest", + "containerDestination": "/var/dest", + "accessMode": "rw" + } + ], + "ports": [ + { + "internal": 1, + "external": 1, + "publicMode": false + } + ], + "routes": [] + }; + + const newMicroserviceUuid = 'newMicroserviceUuid'; + const newMicroservice = { + uuid: newMicroserviceUuid, + name: microserviceData.name, + config: microserviceData.config, + catalogItemId: microserviceData.catalogItemId, + flowId: microserviceData.flowId, + iofogUuid: microserviceData.iofogUuid, + rootHostAccess: microserviceData.rootHostAccess, + logSize: microserviceData.logLimit, + userId: user.id + }; + + const item = {}; + + const portMappingData = + { + "internal": 1, + "external": 1, + "publicMode": false + }; + + const mappings = []; + for (const volumeMapping of microserviceData.volumeMappings) { + const mapping = Object.assign({}, volumeMapping); + mapping.microserviceUuid = microserviceData.uuid; + mappings.push(mapping); + } + + const mappingData = { + isPublic: false, + portInternal: portMappingData.internal, + portExternal: portMappingData.external, + userId: microserviceData.userId, + microserviceUuid: microserviceData.uuid + }; + + def('subject', () => $subject.createMicroservice(microserviceData, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('validatorResponse2', () => Promise.resolve(true)); + def('generateRandomStringResponse', () => newMicroserviceUuid); + def('deleteUndefinedFieldsResponse', () => newMicroservice); + def('findMicroserviceResponse', () => Promise.resolve()); + def('findMicroserviceResponse2', () => Promise.resolve(microserviceData)); + def('getCatalogItemResponse', () => Promise.resolve()); + def('getFlowResponse', () => Promise.resolve()); + def('getIoFogResponse', () => Promise.resolve()); + def('createMicroserviceResponse', () => Promise.resolve(microserviceData)); + def('findMicroservicePortResponse', () => Promise.resolve()); + def('createMicroservicePortResponse', () => Promise.resolve()); + def('updateMicroserviceResponse', () => Promise.resolve()); + def('updateChangeTrackingResponse', () => Promise.resolve()); + def('createVolumeMappingResponse', () => Promise.resolve()); + def('createMicroserviceStatusResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate') + .onFirstCall().returns($validatorResponse) + .onSecondCall().returns($validatorResponse2); + $sandbox.stub(AppHelper, 'generateRandomString').returns($generateRandomStringResponse); + $sandbox.stub(AppHelper, 'deleteUndefinedFields').returns($deleteUndefinedFieldsResponse); + $sandbox.stub(MicroserviceManager, 'findOne') + .onFirstCall().returns($findMicroserviceResponse) + .onSecondCall().returns($findMicroserviceResponse2); + $sandbox.stub(CatalogService, 'getCatalogItem').returns($getCatalogItemResponse); + $sandbox.stub(FlowService, 'getFlow').returns($getFlowResponse); + $sandbox.stub(ioFogService, 'getFog').returns($getIoFogResponse); + $sandbox.stub(MicroserviceManager, 'create').returns($createMicroserviceResponse); + $sandbox.stub(MicroservicePortManager, 'findOne').returns($findMicroservicePortResponse); + $sandbox.stub(MicroservicePortManager, 'create').returns($createMicroservicePortResponse); + $sandbox.stub(MicroserviceManager, 'update').returns($updateMicroserviceResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + $sandbox.stub(VolumeMappingManager, 'bulkCreate').returns($createVolumeMappingResponse); + $sandbox.stub(MicroserviceStatusManager, 'create').returns($createMicroserviceStatusResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(microserviceData, + Validator.schemas.microserviceCreate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls AppHelper#generateRandomString() with correct args', async () => { + await $subject; + expect(AppHelper.generateRandomString).to.have.been.calledWith(32); + }); + + context('when AppHelper#generateRandomString() fails', () => { + def('generateRandomStringResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('uuid'); + }) + }); + + context('when AppHelper#generateRandomString() succeeds', () => { + it('calls AppHelper#deleteUndefinedFields() with correct args', async () => { + await $subject; + expect(AppHelper.deleteUndefinedFields).to.have.been.calledWith(newMicroservice); + }); + + context('when AppHelper#deleteUndefinedFields() fails', () => { + const err = 'Invalid microservice UUID \'undefined\''; + def('deleteUndefinedFieldsResponse', () => Promise.reject(err)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(err); + }) + }); + + context('when AppHelper#deleteUndefinedFields() succeeds', () => { + it('calls MicroserviceManager#findOne() with correct args', async () => { + await $subject; + const where = item.id + ? + { + name: microserviceData.name, + uuid: {[Op.ne]: item.id}, + userId: user.id + } + : + { + name: microserviceData.name, + userId: user.id + }; + expect(MicroserviceManager.findOne).to.have.been.calledWith(where, transaction); + }); + + context('when MicroserviceManager#findOne() fails', () => { + def('findMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#findOne() succeeds', () => { + it('calls CatalogService#getCatalogItem() with correct args', async () => { + await $subject; + expect(CatalogService.getCatalogItem).to.have.been.calledWith(newMicroservice.catalogItemId, + user, isCLI, transaction); + }); + + context('when CatalogService#getCatalogItem() fails', () => { + def('getCatalogItemResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when CatalogService#getCatalogItem() succeeds', () => { + it('calls FlowService#getFlow() with correct args', async () => { + await $subject; + expect(FlowService.getFlow).to.have.been.calledWith(newMicroservice.flowId, + user, isCLI, transaction); + }); + + context('when FlowService#getFlow() fails', () => { + def('getFlowResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when FlowService#getFlow() succeeds', () => { + it('calls IoFogService#getFog() with correct args', async () => { + await $subject; + expect(ioFogService.getFog).to.have.been.calledWith({ + uuid: newMicroservice.iofogUuid + }, user, isCLI, transaction); + }); + + context('when IoFogService#getFog() fails', () => { + def('getIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when IoFogService#getFog() succeeds', () => { + it('calls MicroserviceManager#create() with correct args', async () => { + await $subject; + expect(MicroserviceManager.create).to.have.been.calledWith(newMicroservice, + transaction); + }); + + context('when MicroserviceManager#create() fails', () => { + def('getIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#create() succeeds', () => { + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(portMappingData, Validator.schemas.portsCreate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse2', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls MicroserviceManager#findOne() with correct args', async () => { + await $subject; + const where = isCLI + ? {uuid: microserviceData.uuid} + : {uuid: microserviceData.uuid, userId: user.id}; + expect(MicroserviceManager.findOne).to.have.been.calledWith(where, transaction); + }); + + context('when MicroserviceManager#findOne() fails', () => { + def('findMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#findOne() succeeds', () => { + it('calls MicroservicePortManager#findOne() with correct args', async () => { + await $subject; + expect(MicroservicePortManager.findOne).to.have.been.calledWith({ + microserviceUuid: microserviceData.uuid, + [Op.or]: + [ + { + portInternal: portMappingData.internal + }, + { + portExternal: portMappingData.external + } + ] + }, transaction); + }); + + context('when MicroservicePortManager#findOne() fails', () => { + def('findMicroservicePortResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroservicePortManager#findOne() succeeds', () => { + it('calls MicroservicePortManager#create() with correct args', async () => { + await $subject; + expect(MicroservicePortManager.create).to.have.been.calledWith(mappingData, transaction); + }); + + context('when MicroservicePortManager#create() fails', () => { + def('createMicroservicePortResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroservicePortManager#create() succeeds', () => { + it('calls MicroserviceManager#update() with correct args', async () => { + await $subject; + const updateRebuildMs = { + rebuild: true + }; + expect(MicroserviceManager.update).to.have.been.calledWith({ + uuid: microserviceData.uuid + }, updateRebuildMs, transaction); + }); + + context('when MicroserviceManager#update() fails', () => { + def('updateMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#update() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + expect(ChangeTrackingService.update).to.have.been.calledWith(microserviceData.iofogUuid, + ChangeTrackingService.events.microserviceConfig, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('calls VolumeMappingManager#bulkCreate() with correct args', async () => { + await $subject; + expect(VolumeMappingManager.bulkCreate).to.have.been.calledWith(mappings, + transaction); + }); + + context('when VolumeMappingManager#bulkCreate() fails', () => { + def('createVolumeMappingResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when VolumeMappingManager#bulkCreate() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + expect(ChangeTrackingService.update).to.have.been.calledWith(microserviceData.iofogUuid, + ChangeTrackingService.events.microserviceList, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('calls MicroserviceStatusManager#create() with correct args', async () => { + await $subject; + expect(MicroserviceStatusManager.create).to.have.been.calledWith({ + microserviceUuid: microserviceData.uuid + }, transaction); + }); + + context('when MicroserviceStatusManager#create() fails', () => { + def('createMicroserviceStatusResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceStatusManager#create() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('uuid'); + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }); +// +// describe('.updateMicroservice()', () => { +// const transaction = {}; +// const error = 'Error!'; +// +// const user = { +// id: 15 +// }; +// +// const microserviceUuid = 'testMicroserviceUuid'; +// +// const query = isCLI +// ? +// { +// uuid: microserviceUuid +// } +// : +// { +// uuid: microserviceUuid, +// userId: user.id +// }; +// +// const microserviceData = { +// "name": "name2", +// "config": "string", +// "catalogItemId": 15, +// "flowId": 16, +// "iofogUuid": 'testIofogUuid', +// "rootHostAccess": true, +// "logSize": 0, +// "volumeMappings": [ +// { +// "hostDestination": "/var/dest", +// "containerDestination": "/var/dest", +// "accessMode": "rw" +// } +// ], +// "ports": [ +// { +// "internal": 1, +// "external": 1, +// "publicMode": false +// } +// ], +// "routes": [] +// }; +// +// const microserviceToUpdate = { +// name: microserviceData.name, +// config: microserviceData.config, +// rebuild: microserviceData.rebuild, +// iofogUuid: microserviceData.iofogUuid, +// rootHostAccess: microserviceData.rootHostAccess, +// logSize: microserviceData.logLimit, +// volumeMappings: microserviceData.volumeMappings +// }; +// +// const newMicroserviceUuid = 'newMicroserviceUuid'; +// const newMicroservice = { +// uuid: newMicroserviceUuid, +// name: microserviceData.name, +// config: microserviceData.config, +// catalogItemId: microserviceData.catalogItemId, +// flowId: microserviceData.flowId, +// iofogUuid: microserviceData.iofogUuid, +// rootHostAccess: microserviceData.rootHostAccess, +// logSize: microserviceData.logLimit, +// userId: user.id +// }; +// +// const item = {}; +// +// const portMappingData = +// { +// "internal": 1, +// "external": 1, +// "publicMode": false +// }; +// +// const mappings = []; +// for (const volumeMapping of microserviceData.volumeMappings) { +// const mapping = Object.assign({}, volumeMapping); +// mapping.microserviceUuid = microserviceData.uuid; +// mappings.push(mapping); +// } +// +// const mappingData = { +// isPublic: false, +// portInternal: portMappingData.internal, +// portExternal: portMappingData.external, +// userId: microserviceData.userId, +// microserviceUuid: microserviceData.uuid +// }; +// +// def('subject', () => $subject.updateMicroservice(microserviceUuid, microserviceData, user, isCLI, transaction)); +// def('validatorResponse', () => Promise.resolve(true)); +// def('deleteUndefinedFieldsResponse', () => newMicroservice); +// def('findMicroserviceResponse', () => Promise.resolve()); +// def('findMicroserviceResponse2', () => Promise.resolve(microserviceData)); +// def('getIoFogResponse', () => Promise.resolve()); +// def('updateMicroserviceResponse', () => Promise.resolve()); +// def('updateVolumeMappingResponse', () => Promise.resolve()); +// // TODO +// +// def('updateChangeTrackingResponse', () => Promise.resolve()); +// def('updateChangeTrackingResponse2', () => Promise.resolve()); +// def('updateChangeTrackingResponse3', () => Promise.resolve()); +// +// beforeEach(() => { +// $sandbox.stub(Validator, 'validate').returns($validatorResponse); +// $sandbox.stub(AppHelper, 'deleteUndefinedFields').returns($deleteUndefinedFieldsResponse); +// $sandbox.stub(MicroserviceManager, 'findOne') +// .onFirstCall().returns($findMicroserviceResponse) +// .onSecondCall().returns($findMicroserviceResponse2); +// $sandbox.stub(ioFogService, 'getFog').returns($getIoFogResponse); +// $sandbox.stub(MicroserviceManager, 'update').returns($updateMicroserviceResponse); +// $sandbox.stub(VolumeMappingManager, 'update').returns($updateVolumeMappingResponse); +// $sandbox.stub(RoutingManager, 'findAll').returns($findAllRoutesResponse); +// +// // TODO +// // delete route endpoint +// // create route endpoint +// $sandbox.stub(ChangeTrackingService, 'update') +// .onFirstCall().returns($updateChangeTrackingResponse) +// .onSecondCall().returns($updateChangeTrackingResponse2) +// .onThirdCall().returns($updateChangeTrackingResponse3); +// }); +// +// it('calls Validator#validate() with correct args', async () => { +// await $subject; +// expect(Validator.validate).to.have.been.calledWith(microserviceData, +// Validator.schemas.microserviceCreate); +// }); +// +// context('when Validator#validate() fails', () => { +// def('validatorResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when Validator#validate() succeeds', () => { +// it('calls AppHelper#generateRandomString() with correct args', async () => { +// await $subject; +// expect(AppHelper.generateRandomString).to.have.been.calledWith(32); +// }); +// +// context('when AppHelper#generateRandomString() fails', () => { +// def('generateRandomStringResponse', () => error); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.eventually.have.property('uuid'); +// }) +// }); +// +// context('when AppHelper#generateRandomString() succeeds', () => { +// it('calls AppHelper#deleteUndefinedFields() with correct args', async () => { +// await $subject; +// expect(AppHelper.deleteUndefinedFields).to.have.been.calledWith(newMicroservice); +// }); +// +// context('when AppHelper#deleteUndefinedFields() fails', () => { +// const err = 'Invalid microservice UUID \'undefined\''; +// def('deleteUndefinedFieldsResponse', () => Promise.reject(err)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(err); +// }) +// }); +// +// context('when AppHelper#deleteUndefinedFields() succeeds', () => { +// it('calls MicroserviceManager#findOne() with correct args', async () => { +// await $subject; +// const where = item.id +// ? +// { +// name: microserviceData.name, +// uuid: {[Op.ne]: item.id}, +// userId: user.id +// } +// : +// { +// name: microserviceData.name, +// userId: user.id +// }; +// expect(MicroserviceManager.findOne).to.have.been.calledWith(where, transaction); +// }); +// +// context('when MicroserviceManager#findOne() fails', () => { +// def('findMicroserviceResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroserviceManager#findOne() succeeds', () => { +// it('calls CatalogService#getCatalogItem() with correct args', async () => { +// await $subject; +// expect(CatalogService.getCatalogItem).to.have.been.calledWith(newMicroservice.catalogItemId, +// user, isCLI, transaction); +// }); +// +// context('when CatalogService#getCatalogItem() fails', () => { +// def('getCatalogItemResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when CatalogService#getCatalogItem() succeeds', () => { +// it('calls FlowService#getFlow() with correct args', async () => { +// await $subject; +// expect(FlowService.getFlow).to.have.been.calledWith(newMicroservice.flowId, +// user, isCLI, transaction); +// }); +// +// context('when FlowService#getFlow() fails', () => { +// def('getFlowResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when FlowService#getFlow() succeeds', () => { +// it('calls IoFogService#getFog() with correct args', async () => { +// await $subject; +// expect(ioFogService.getFog).to.have.been.calledWith({ +// uuid: newMicroservice.iofogUuid +// }, user, isCLI, transaction); +// }); +// +// context('when IoFogService#getFog() fails', () => { +// def('getIoFogResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when IoFogService#getFog() succeeds', () => { +// it('calls MicroserviceManager#create() with correct args', async () => { +// await $subject; +// expect(MicroserviceManager.create).to.have.been.calledWith(newMicroservice, +// transaction); +// }); +// +// context('when MicroserviceManager#create() fails', () => { +// def('getIoFogResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroserviceManager#create() succeeds', () => { +// it('calls Validator#validate() with correct args', async () => { +// await $subject; +// expect(Validator.validate).to.have.been.calledWith(portMappingData, Validator.schemas.portsCreate); +// }); +// +// context('when Validator#validate() fails', () => { +// def('validatorResponse2', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when Validator#validate() succeeds', () => { +// it('calls MicroserviceManager#findOne() with correct args', async () => { +// await $subject; +// const where = isCLI +// ? {uuid: microserviceData.uuid} +// : {uuid: microserviceData.uuid, userId: user.id}; +// expect(MicroserviceManager.findOne).to.have.been.calledWith(where, transaction); +// }); +// +// context('when MicroserviceManager#findOne() fails', () => { +// def('findMicroserviceResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroserviceManager#findOne() succeeds', () => { +// it('calls MicroservicePortManager#findOne() with correct args', async () => { +// await $subject; +// expect(MicroservicePortManager.findOne).to.have.been.calledWith({ +// microserviceUuid: microserviceData.uuid, +// [Op.or]: +// [ +// { +// portInternal: portMappingData.internal +// }, +// { +// portExternal: portMappingData.external +// } +// ] +// }, transaction); +// }); +// +// context('when MicroservicePortManager#findOne() fails', () => { +// def('findMicroservicePortResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroservicePortManager#findOne() succeeds', () => { +// it('calls MicroservicePortManager#create() with correct args', async () => { +// await $subject; +// expect(MicroservicePortManager.create).to.have.been.calledWith(mappingData, transaction); +// }); +// +// context('when MicroservicePortManager#create() fails', () => { +// def('createMicroservicePortResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroservicePortManager#create() succeeds', () => { +// it('calls MicroserviceManager#update() with correct args', async () => { +// await $subject; +// const updateRebuildMs = { +// rebuild: true +// }; +// expect(MicroserviceManager.update).to.have.been.calledWith({ +// uuid: microserviceData.uuid +// }, updateRebuildMs, transaction); +// }); +// +// context('when MicroserviceManager#update() fails', () => { +// def('updateMicroserviceResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroserviceManager#update() succeeds', () => { +// it('calls ChangeTrackingService#update() with correct args', async () => { +// await $subject; +// expect(ChangeTrackingService.update).to.have.been.calledWith(microserviceData.iofogUuid, +// ChangeTrackingService.events.microserviceConfig, transaction); +// }); +// +// context('when ChangeTrackingService#update() fails', () => { +// def('updateChangeTrackingResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when ChangeTrackingService#update() succeeds', () => { +// it('calls VolumeMappingManager#bulkCreate() with correct args', async () => { +// await $subject; +// expect(VolumeMappingManager.bulkCreate).to.have.been.calledWith(mappings, +// transaction); +// }); +// +// context('when VolumeMappingManager#bulkCreate() fails', () => { +// def('createVolumeMappingResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when VolumeMappingManager#bulkCreate() succeeds', () => { +// it('calls ChangeTrackingService#update() with correct args', async () => { +// await $subject; +// expect(ChangeTrackingService.update).to.have.been.calledWith(microserviceData.iofogUuid, +// ChangeTrackingService.events.microserviceList, transaction); +// }); +// +// context('when ChangeTrackingService#update() fails', () => { +// def('updateChangeTrackingResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when ChangeTrackingService#update() succeeds', () => { +// it('calls MicroserviceStatusManager#create() with correct args', async () => { +// await $subject; +// expect(MicroserviceStatusManager.create).to.have.been.calledWith({ +// microserviceUuid: microserviceData.uuid +// }, transaction); +// }); +// +// context('when MicroserviceStatusManager#create() fails', () => { +// def('createMicroserviceStatusResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroserviceStatusManager#create() succeeds', () => { +// it('fulfills the promise', () => { +// return expect($subject).to.eventually.have.property('uuid'); +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }); +// +// +// describe('.deleteMicroservice()', () => { +// const transaction = {}; +// const error = 'Error!'; +// +// const user = { +// id: 15 +// }; +// +// const microserviceUuid = 'testMicroserviceUuid'; +// +// const microserviceData = { +// "name": "name2", +// "config": "string", +// "catalogItemId": 15, +// "flowId": 16, +// "iofogUuid": 'testIofogUuid', +// "rootHostAccess": true, +// "logSize": 0, +// "volumeMappings": [ +// { +// "hostDestination": "/var/dest", +// "containerDestination": "/var/dest", +// "accessMode": "rw" +// } +// ], +// "ports": [ +// { +// "internal": 1, +// "external": 1, +// "publicMode": false +// } +// ], +// "routes": [] +// }; +// +// const portMappingData = [ +// { +// "internal": 1, +// "external": 1, +// "publicMode": false +// } +// ]; +// +// +// const where = isCLI +// ? +// { +// uuid: microserviceUuid, +// } +// : +// { +// uuid: microserviceUuid, +// userId: user.id +// }; +// +// const mappingData = { +// isPublic: false, +// portInternal: portMappingData.internal, +// portExternal: portMappingData.external, +// userId: microserviceData.userId, +// microserviceUuid: microserviceData.uuid +// }; +// +// def('subject', () => $subject.deleteMicroservice(microserviceUuid, microserviceData, user, isCLI, transaction)); +// def('findMicroserviceResponse', () => Promise.resolve(microserviceData)); +// def('findMicroservicePortResponse', () => Promise.resolve()); +// def('deleteMicroservicePortResponse', () => Promise.resolve()); +// def('updateMicroserviceResponse', () => Promise.resolve()); +// def('updateChangeTrackingResponse', () => Promise.resolve()); +// +// beforeEach(() => { +// $sandbox.stub(MicroserviceManager, 'findOneWithStatus').returns($findMicroserviceResponse); +// $sandbox.stub(MicroservicePortManager, 'findAll').returns($findMicroservicePortResponse); +// $sandbox.stub(MicroservicePortManager, 'delete').returns($deleteMicroservicePortResponse); +// $sandbox.stub(MicroserviceManager, 'update').returns($updateMicroserviceResponse); +// $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); +// }); +// +// it('calls Validator#validate() with correct args', async () => { +// await $subject; +// expect(Validator.validate).to.have.been.calledWith(portMappingData, Validator.schemas.portsCreate); +// }); +// +// context('when Validator#validate() fails', () => { +// def('validatorResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when Validator#validate() succeeds', () => { +// it('calls MicroserviceManager#findOne() with correct args', async () => { +// await $subject; +// expect(MicroserviceManager.findOne).to.have.been.calledWith(where, transaction); +// }); +// +// context('when MicroserviceManager#findOne() fails', () => { +// def('findMicroserviceResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroserviceManager#findOne() succeeds', () => { +// it('calls MicroservicePortManager#findOne() with correct args', async () => { +// await $subject; +// expect(MicroservicePortManager.findOne).to.have.been.calledWith({ +// microserviceUuid: microserviceUuid, +// [Op.or]: +// [ +// { +// portInternal: portMappingData.internal +// }, +// { +// portExternal: portMappingData.external +// } +// ] +// }, transaction); +// }); +// +// context('when MicroservicePortManager#findOne() fails', () => { +// def('findMicroservicePortResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroservicePortManager#findOne() succeeds', () => { +// it('calls MicroservicePortManager#create() with correct args', async () => { +// await $subject; +// expect(MicroservicePortManager.create).to.have.been.calledWith(mappingData, transaction); +// }); +// +// context('when MicroservicePortManager#create() fails', () => { +// def('createMicroservicePortResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroservicePortManager#create() succeeds', () => { +// it('calls MicroserviceManager#update() with correct args', async () => { +// await $subject; +// const updateRebuildMs = { +// rebuild: true +// }; +// expect(MicroserviceManager.update).to.have.been.calledWith({ +// uuid: microserviceData.uuid +// }, updateRebuildMs, transaction); +// }); +// +// context('when MicroserviceManager#update() fails', () => { +// def('updateMicroserviceResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroserviceManager#update() succeeds', () => { +// it('calls ChangeTrackingService#update() with correct args', async () => { +// await $subject; +// expect(ChangeTrackingService.update).to.have.been.calledWith(microserviceData.iofogUuid, +// ChangeTrackingService.events.microserviceConfig, transaction); +// }); +// +// context('when ChangeTrackingService#update() fails', () => { +// def('updateChangeTrackingResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when ChangeTrackingService#update() succeeds', () => { +// it('fulfills the promise', () => { +// return expect($subject).eventually.equals(undefined); +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }); +// +// }); +// + + describe('.createPortMapping()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const microserviceUuid = 'testMicroserviceUuid'; + + const microserviceData = { + "name": "name2", + "config": "string", + "catalogItemId": 15, + "flowId": 16, + "iofogUuid": 'testIofogUuid', + "rootHostAccess": true, + "logSize": 0, + "volumeMappings": [ + { + "hostDestination": "/var/dest", + "containerDestination": "/var/dest", + "accessMode": "rw" + } + ], + "ports": [ + { + "internal": 1, + "external": 1, + "publicMode": false + } + ], + "routes": [] + }; + + const portMappingData = [ + { + "internal": 1, + "external": 1, + "publicMode": false + } + ]; + + const where = isCLI + ? {uuid: microserviceUuid} + : {uuid: microserviceUuid, userId: user.id}; + + const mappingData = { + isPublic: false, + portInternal: portMappingData.internal, + portExternal: portMappingData.external, + userId: microserviceData.userId, + microserviceUuid: microserviceData.uuid + }; + + def('subject', () => $subject.createPortMapping(microserviceUuid, portMappingData, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findMicroserviceResponse', () => Promise.resolve(microserviceData)); + def('findMicroservicePortResponse', () => Promise.resolve()); + def('createMicroservicePortResponse', () => Promise.resolve()); + def('updateMicroserviceResponse', () => Promise.resolve()); + def('updateChangeTrackingResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(MicroserviceManager, 'findOne').returns($findMicroserviceResponse); + $sandbox.stub(MicroservicePortManager, 'findOne').returns($findMicroservicePortResponse); + $sandbox.stub(MicroservicePortManager, 'create').returns($createMicroservicePortResponse); + $sandbox.stub(MicroserviceManager, 'update').returns($updateMicroserviceResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(portMappingData, Validator.schemas.portsCreate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls MicroserviceManager#findOne() with correct args', async () => { + await $subject; + expect(MicroserviceManager.findOne).to.have.been.calledWith(where, transaction); + }); + + context('when MicroserviceManager#findOne() fails', () => { + def('findMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#findOne() succeeds', () => { + it('calls MicroservicePortManager#findOne() with correct args', async () => { + await $subject; + expect(MicroservicePortManager.findOne).to.have.been.calledWith({ + microserviceUuid: microserviceUuid, + [Op.or]: + [ + { + portInternal: portMappingData.internal + }, + { + portExternal: portMappingData.external + } + ] + }, transaction); + }); + + context('when MicroservicePortManager#findOne() fails', () => { + def('findMicroservicePortResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroservicePortManager#findOne() succeeds', () => { + it('calls MicroservicePortManager#create() with correct args', async () => { + await $subject; + expect(MicroservicePortManager.create).to.have.been.calledWith(mappingData, transaction); + }); + + context('when MicroservicePortManager#create() fails', () => { + def('createMicroservicePortResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroservicePortManager#create() succeeds', () => { + it('calls MicroserviceManager#update() with correct args', async () => { + await $subject; + const updateRebuildMs = { + rebuild: true + }; + expect(MicroserviceManager.update).to.have.been.calledWith({ + uuid: microserviceData.uuid + }, updateRebuildMs, transaction); + }); + + context('when MicroserviceManager#update() fails', () => { + def('updateMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#update() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + expect(ChangeTrackingService.update).to.have.been.calledWith(microserviceData.iofogUuid, + ChangeTrackingService.events.microserviceConfig, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).eventually.equals(undefined); + }) + }) + }) + }) + }) + }) + }) + }); + +}); \ No newline at end of file diff --git a/test/src/services/registry-service.test.js b/test/src/services/registry-service.test.js new file mode 100644 index 000000000..111a99bd0 --- /dev/null +++ b/test/src/services/registry-service.test.js @@ -0,0 +1,486 @@ +const {expect} = require('chai'); +const sinon = require('sinon'); + +const RegistryManager = require('../../../src/sequelize/managers/registry-manager'); +const RegistryService = require('../../../src/services/registry-service'); +const Validator = require('../../../src/schemas'); +const AppHelper = require('../../../src/helpers/app-helper'); +const ioFogManager = require('../../../src/sequelize/managers/iofog-manager'); +const ChangeTrackingService = require('../../../src/services/change-tracking-service'); +const Sequelize = require('sequelize'); +const Op = Sequelize.Op; + +describe('Registry Service', () => { + def('subject', () => RegistryService); + def('sandbox', () => sinon.createSandbox()); + + const isCLI = false; + + afterEach(() => $sandbox.restore()); + + describe('.createRegistry()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const registry = { + url: 'testUrl', + username: 'testUsername', + password: 'testPassword', + isPublic: false, + userEmail: 'testEmail', + requiresCert: false, + certificate: 'testCertificate', + userId: user.id + }; + + const registryCreate = { + url: registry.url, + username: registry.username, + password: registry.password, + isPublic: registry.isPublic, + userEmail: registry.email, + requiresCert: registry.requiresCert, + certificate: registry.certificate, + userId: user.id + }; + + const ioFogs = [{ + uuid: 'testUuid' + }]; + + def('subject', () => $subject.createRegistry(registry, user, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('deleteUndefinedFieldsResponse', () => registryCreate); + def('createRegistryResponse', () => Promise.resolve({ + id: 16 + })); + def('findIoFogsResponse', () => Promise.resolve(ioFogs)); + def('updateChangeTrackingResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(AppHelper, 'deleteUndefinedFields').returns($deleteUndefinedFieldsResponse); + $sandbox.stub(RegistryManager, 'create').returns($createRegistryResponse); + $sandbox.stub(ioFogManager, 'findAll').returns($findIoFogsResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(registry, Validator.schemas.registryCreate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls AppHelper#deleteUndefinedFields() with correct args', async () => { + await $subject; + expect(AppHelper.deleteUndefinedFields).to.have.been.calledWith(registryCreate); + }); + + context('when AppHelper#deleteUndefinedFields() fails', () => { + def('deleteUndefinedFieldsResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('id'); + }) + }); + + context('when AppHelper#deleteUndefinedFields() succeeds', () => { + it('calls RegistryManager#create() with correct args', async () => { + await $subject; + expect(RegistryManager.create).to.have.been.calledWith(registryCreate, transaction); + }); + + context('when RegistryManager#create() fails', () => { + def('createRegistryResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when RegistryManager#create() succeeds', () => { + it('calls ioFogManager#findAll() with correct args', async () => { + await $subject; + expect(ioFogManager.findAll).to.have.been.calledWith({ + userId: user.id + }, transaction); + }); + + context('when ioFogManager#findAll() fails', () => { + def('findIoFogsResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#findAll() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + expect(ChangeTrackingService.update).to.have.been.calledWith(ioFogs[0].uuid, + ChangeTrackingService.events.registries, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('findIoFogsResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('id'); + }) + }) + }) + }) + }) + }) + }); + + describe('.findRegistries()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const queryRegistry = isCLI + ? {} + : { + [Op.or]: + [ + { + userId: user.id + }, + { + isPublic: true + } + ] + }; + + def('subject', () => $subject.findRegistries(user, isCLI, transaction)); + def('findRegistriesResponse', () => Promise.resolve([])); + + beforeEach(() => { + $sandbox.stub(RegistryManager, 'findAll').returns($findRegistriesResponse); + }); + + it('calls RegistryManager#findAll() with correct args', async () => { + await $subject; + expect(RegistryManager.findAll).to.have.been.calledWith(queryRegistry, transaction); + }); + + context('when RegistryManager#findAll() fails', () => { + def('findRegistriesResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when RegistryManager#findAll() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('registries'); + }) + }) + }); + + describe('.deleteRegistry()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const registryData = { + id: 5 + }; + + const queryData = isCLI + ? {id: registryData.id} + : {id: registryData.id, userId: user.id}; + + const ioFogs = [{ + uuid: 'testUuid' + }]; + + def('subject', () => $subject.deleteRegistry(registryData, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findRegistryResponse', () => Promise.resolve({ + userId: user.id + })); + def('deleteRegistryResponse', () => Promise.resolve()); + def('findIoFogsResponse', () => Promise.resolve(ioFogs)); + def('updateChangeTrackingResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(RegistryManager, 'findOne').returns($findRegistryResponse); + $sandbox.stub(RegistryManager, 'delete').returns($deleteRegistryResponse); + $sandbox.stub(ioFogManager, 'findAll').returns($findIoFogsResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(registryData, Validator.schemas.registryDelete); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls RegistryManager#findOne() with correct args', async () => { + await $subject; + expect(RegistryManager.findOne).to.have.been.calledWith(queryData, transaction); + }); + + context('when RegistryManager#findOne() fails', () => { + def('findRegistryResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when RegistryManager#findOne() succeeds', () => { + it('calls RegistryManager#delete() with correct args', async () => { + await $subject; + expect(RegistryManager.delete).to.have.been.calledWith(queryData, transaction); + }); + + context('when RegistryManager#delete() fails', () => { + def('deleteRegistryResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when RegistryManager#delete() succeeds', () => { + it('calls ioFogManager#findAll() with correct args', async () => { + await $subject; + expect(ioFogManager.findAll).to.have.been.calledWith({ + userId: user.id + }, transaction); + }); + + context('when ioFogManager#findAll() fails', () => { + def('findIoFogsResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#findAll() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + expect(ChangeTrackingService.update).to.have.been.calledWith(ioFogs[0].uuid, + ChangeTrackingService.events.registries, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('findIoFogsResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined); + }) + }) + }) + }) + }) + }) + }); + + describe('.updateRegistry()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const registryId = 5; + + const registry = { + url: 'testUrl', + username: 'testUsername', + password: 'testPassword', + isPublic: false, + userEmail: 'testEmail', + requiresCert: false, + certificate: 'testCertificate', + userId: user.id + }; + + let registryUpdate = { + url: registry.url, + username: registry.username, + password: registry.password, + isPublic: registry.isPublic, + userEmail: registry.email, + requiresCert: registry.requiresCert, + certificate: registry.certificate + }; + + const ioFogs = [{ + uuid: 'testUuid' + }]; + + const where = isCLI ? + { + id: registryId + } + : + { + id: registryId, + userId: user.id + }; + + def('subject', () => $subject.updateRegistry(registry, registryId, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findRegistryResponse', () => Promise.resolve({})); + def('deleteUndefinedFieldsResponse', () => registryUpdate); + def('updateRegistryResponse', () => Promise.resolve()); + def('findIoFogsResponse', () => Promise.resolve(ioFogs)); + def('updateChangeTrackingResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(RegistryManager, 'findOne').returns($findRegistryResponse); + $sandbox.stub(AppHelper, 'deleteUndefinedFields').returns($deleteUndefinedFieldsResponse); + $sandbox.stub(RegistryManager, 'update').returns($updateRegistryResponse); + $sandbox.stub(ioFogManager, 'findAll').returns($findIoFogsResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(registry, Validator.schemas.registryUpdate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls RegistryManager#findOne() with correct args', async () => { + await $subject; + expect(RegistryManager.findOne).to.have.been.calledWith({ + id: registryId + }, transaction); + }); + + context('when RegistryManager#findOne() fails', () => { + def('findRegistryResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when RegistryManager#findOne() succeeds', () => { + it('calls AppHelper#deleteUndefinedFields() with correct args', async () => { + await $subject; + expect(AppHelper.deleteUndefinedFields).to.have.been.calledWith(registryUpdate); + }); + + context('when AppHelper#deleteUndefinedFields() fails', () => { + def('deleteUndefinedFieldsResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + + context('when AppHelper#deleteUndefinedFields() succeeds', () => { + it('calls RegistryManager#update() with correct args', async () => { + await $subject; + expect(RegistryManager.update).to.have.been.calledWith(where, registryUpdate, transaction); + }); + + context('when RegistryManager#update() fails', () => { + def('updateRegistryResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when RegistryManager#update() succeeds', () => { + it('calls ioFogManager#findAll() with correct args', async () => { + await $subject; + expect(ioFogManager.findAll).to.have.been.calledWith({ + userId: user.id + }, transaction); + }); + + context('when ioFogManager#findAll() fails', () => { + def('findIoFogsResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#findAll() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + expect(ChangeTrackingService.update).to.have.been.calledWith(ioFogs[0].uuid, + ChangeTrackingService.events.registries, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('findIoFogsResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined); + }) + }) + }) + }) + }) + }) + }) + }); + +}); \ No newline at end of file diff --git a/test/src/services/user-service.test.js b/test/src/services/user-service.test.js new file mode 100644 index 000000000..093213ed9 --- /dev/null +++ b/test/src/services/user-service.test.js @@ -0,0 +1,694 @@ +const {expect} = require('chai'); +const sinon = require('sinon'); + +const UserManager = require('../../../src/sequelize/managers/user-manager'); +const UserService = require('../../../src/services/user-service'); +const Config = require('../../../src/config'); +const AccessTokenService = require('../../../src/services/access-token-service'); +const Validator = require('../../../src/schemas'); +const AppHelper = require('../../../src/helpers/app-helper'); +const ioFogManager = require('../../../src/sequelize/managers/iofog-manager'); +const ChangeTrackingService = require('../../../src/services/change-tracking-service'); +const EmailActivationCodeService = require('../../../src/services/email-activation-code-service'); +const Sequelize = require('sequelize'); +const Op = Sequelize.Op; +const ErrorMessages = require('../../../src/helpers/error-messages'); +const nodemailer = require('nodemailer'); + +describe('User Service', () => { + def('subject', () => UserService); + def('sandbox', () => sinon.createSandbox()); + + const isCLI = false; + + afterEach(() => $sandbox.restore()); + + describe('.signUp()', () => { + const transaction = {}; + const error = 'Error!'; + + const newUser = { + id: 16, + firstName: 'testFirstName', + lastName: 'testLastName', + email: 'testEmail', + emailActivated: true + }; + + const response = { + userId: 16, + firstName: newUser.firstName, + lastName: newUser.lastName, + email: newUser.email, + emailActivated: newUser.emailActivated + }; + + def('subject', () => $subject.signUp(newUser, isCLI, transaction)); + def('configGetResponse', () => false); + def('findUserResponse', () => Promise.resolve()); + def('createUserResponse', () => Promise.resolve(newUser)); + + beforeEach(() => { + $sandbox.stub(Config, 'get').returns($configGetResponse); + $sandbox.stub(UserManager, 'findOne').returns($findUserResponse); + $sandbox.stub(UserManager, 'create').returns($createUserResponse); + }); + + it('calls Config#get() with correct args', async () => { + await $subject; + expect(Config.get).to.have.been.calledWith("Email:ActivationEnabled"); + }); + + context('when Config#get() succeeds', () => { + it('calls UserManager#findOne() with correct args', async () => { + await $subject; + expect(UserManager.findOne).to.have.been.calledWith({ + email: newUser.email + }, transaction); + }); + + context('when UserManager#findOne() fails', () => { + def('findUserResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when UserManager#findOne() succeeds', () => { + it('calls UserManager#create() with correct args', async () => { + await $subject; + expect(UserManager.create).to.have.been.calledWith(newUser, transaction); + }); + + context('when UserManager#create() fails', () => { + def('createUserResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when UserManager#create() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.deep.equal(response); + }) + }) + }) + }) + }); + + describe('.login()', () => { + const transaction = {}; + const error = 'Error!'; + + const credentials = { + email: 'testEmail', + password: 'testPassword' + }; + + const user = { + email: 'testEmail', + password: 'testPassword', + id: 15 + }; + + const testAccessToken = 'testAccessToken'; + + const configGet2 = 155; + const date = 1555; + const tokenExpireTime = date + (configGet2 * 1000); + + const createToken = { + token: testAccessToken, + expirationTime: tokenExpireTime, + userId: user.id + }; + + + def('subject', () => $subject.login(credentials, isCLI, transaction)); + def('findUserResponse', () => Promise.resolve(user)); + def('decryptTextResponse', () => credentials.password); + def('getConfigResponse', () => false); + def('getConfigResponse2', () => configGet2); + def('generateAccessTokenResponse', () => 'testAccessToken'); + def('findByAccessTokenResponse', () => false); + def('createAccessTokenResponse', () => Promise.resolve({ + token: 'token' + })); + def('dateResponse', () => date); + + beforeEach(() => { + $sandbox.stub(UserManager, 'findOne').returns($findUserResponse); + $sandbox.stub(AppHelper, 'decryptText').returns($decryptTextResponse); + $sandbox.stub(Config, 'get') + .onFirstCall().returns($getConfigResponse) + .onSecondCall().returns($getConfigResponse2); + $sandbox.stub(AppHelper, 'generateAccessToken').returns($generateAccessTokenResponse); + $sandbox.stub(UserManager, 'findByAccessToken').returns($findByAccessTokenResponse); + $sandbox.stub(AccessTokenService, 'createAccessToken').returns($createAccessTokenResponse); + $sandbox.stub(Date.prototype, 'getTime').returns($dateResponse); + }); + + it('calls UserManager#findOne() with correct args', async () => { + await $subject; + expect(UserManager.findOne).to.have.been.calledWith({ + email: credentials.email + }, transaction); + }); + + context('when UserManager#findOne() fails', () => { + def('findUserResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when UserManager#findOne() succeeds', () => { + it('calls AppHelper#decryptText() with correct args', async () => { + await $subject; + expect(AppHelper.decryptText).to.have.been.calledWith(user.password, user.email); + }); + + context('when AppHelper#decryptText() fails', () => { + const err = 'Invalid credentials'; + def('decryptTextResponse', () => Promise.reject(err)); + + it(`fails with ${err}`, () => { + return expect($subject).to.be.rejectedWith(err); + }) + }); + + context('when AppHelper#decryptText() succeeds', () => { + it('calls Config#get() with correct args', async () => { + await $subject; + expect(Config.get).to.have.been.calledWith("Email:ActivationEnabled"); + }); + + context('when Config#get() fails', () => { + const err = 'Email is not activated. Please activate your account first.'; + def('getConfigResponse', () => Promise.reject(err)); + + it(`fails with ${err}`, () => { + return expect($subject).to.be.rejectedWith(err); + }) + }); + + context('when Config#get() succeeds', () => { + it('calls AppHelper#generateAccessToken() with correct args', async () => { + await $subject; + expect(AppHelper.generateAccessToken).to.have.been.calledWith(); + }); + + context('when AppHelper#generateAccessToken() fails', () => { + def('generateAccessTokenResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('accessToken'); + }) + }); + + context('when AppHelper#generateAccessToken() succeeds', () => { + it('calls UserManager#findByAccessToken() with correct args', async () => { + await $subject; + expect(UserManager.findByAccessToken).to.have.been.calledWith(testAccessToken, transaction); + }); + + context('when UserManager#findByAccessToken() fails', () => { + def('findByAccessTokenResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when UserManager#findByAccessToken() succeeds', () => { + it('calls Config#get() with correct args', async () => { + await $subject; + expect(Config.get).to.have.been.calledWith('Settings:UserTokenExpirationIntervalSeconds'); + }); + + context('when Config#get() fails', () => { + def('getConfigResponse2', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('accessToken'); + }) + }); + + context('when Config#get() succeeds', () => { + it('calls AccessTokenService#createAccessToken() with correct args', async () => { + await $subject; + expect(AccessTokenService.createAccessToken).to.have.been.calledWith(createToken, transaction); + }); + + context('when AccessTokenService#createAccessToken() fails', () => { + def('createAccessTokenResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when AccessTokenService#createAccessToken() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('accessToken'); + }) + }) + }) + }) + }) + }) + }) + }) + }); + + describe('.resendActivation()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + email: 'testEmail', + password: 'testPassword', + id: 15 + }; + + const configGet2 = 155; + + const emailObj = { + email: 'testEmail' + }; + + def('subject', () => $subject.resendActivation(emailObj, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findUserResponse', () => Promise.resolve(user)); + def('generateActivationCodeResponse', () => Promise.resolve()); + def('saveActivationCodeResponse', () => Promise.resolve()); + def('getConfigResponse', () => false); + def('getConfigResponse2', () => configGet2); + def('getConfigResponse3', () => configGet2); + def('getConfigResponse4', () => configGet2); + def('decryptTextResponse', () => 'testPassword'); + def('createTransportResponse', () => Promise.resolve()); + def('sendMailResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(UserManager, 'findOne').returns($findUserResponse); + $sandbox.stub(EmailActivationCodeService, 'generateActivationCode').returns($generateActivationCodeResponse); + $sandbox.stub(EmailActivationCodeService, 'saveActivationCode').returns($saveActivationCodeResponse); + $sandbox.stub(Config, 'get') + .onCall(0).returns($getConfigResponse) + .onCall(1).returns($getConfigResponse2) + .onCall(2).returns($getConfigResponse3) + .onCall(3).returns($getConfigResponse4); + $sandbox.stub(AppHelper, 'decryptText').returns($decryptTextResponse); + // TODO with rewire + // $sandbox.stub(nodemailer, 'createTransport').returns($createTransportResponse); + // $sandbox.stub(transporter, 'sendmail').returns($sendMailResponse); + }); + + // TODO finish + + }); + + + describe('.activateUser()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + email: 'testEmail', + password: 'testPassword', + id: 15 + }; + + const updatedObj = { + emailActivated: true + }; + + const codeData = { + activationCode: 'testActivationCode' + }; + + def('subject', () => $subject.activateUser(codeData, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('verifyActivationCodeResponse', () => Promise.resolve({ + userId: user.id + })); + def('updateUserResponse', () => Promise.resolve()); + def('deleteActivationCodeResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(EmailActivationCodeService, 'verifyActivationCode').returns($verifyActivationCodeResponse); + $sandbox.stub(UserManager, 'update').returns($updateUserResponse); + $sandbox.stub(EmailActivationCodeService, 'deleteActivationCode').returns($deleteActivationCodeResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(codeData, Validator.schemas.activateUser); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls EmailActivationCodeService#verifyActivationCode() with correct args', async () => { + await $subject; + expect(EmailActivationCodeService.verifyActivationCode).to.have.been.calledWith(codeData.activationCode, transaction); + }); + + context('when EmailActivationCodeService#verifyActivationCode() fails', () => { + def('verifyActivationCodeResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when EmailActivationCodeService#verifyActivationCode() succeeds', () => { + it('calls UserManager#update() with correct args', async () => { + await $subject; + expect(UserManager.update).to.have.been.calledWith({ + id: user.id + }, updatedObj, transaction); + }); + + context('when UserManager#update() fails', () => { + const err = 'User not updated'; + def('updateUserResponse', () => Promise.reject(err)); + + it(`fails with ${err}`, () => { + return expect($subject).to.be.rejectedWith(err); + }) + }); + + context('when UserManager#update() succeeds', () => { + it('calls EmailActivationCodeService#deleteActivationCode() with correct args', async () => { + await $subject; + expect(EmailActivationCodeService.deleteActivationCode).to.have.been.calledWith(codeData.activationCode, + transaction); + }); + + context('when EmailActivationCodeService#deleteActivationCode() fails', () => { + def('deleteActivationCodeResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + + context('when EmailActivationCodeService#deleteActivationCode() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined); + }) + }) + }) + }) + }) + }); + + describe('.logout()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + def('subject', () => $subject.logout(user, isCLI, transaction)); + def('removeAccessTokenResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(AccessTokenService, 'removeAccessTokenByUserId').returns($removeAccessTokenResponse); + }); + + it('calls AccessTokenService#removeAccessTokenByUserId() with correct args', async () => { + await $subject; + expect(AccessTokenService.removeAccessTokenByUserId).to.have.been.calledWith(user.id, transaction); + }); + + context('when AccessTokenService#removeAccessTokenByUserId() fails', () => { + def('removeAccessTokenResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when AccessTokenService#removeAccessTokenByUserId() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined); + }) + }) + }); + + describe('.updateUserDetails()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + email: 'testEmail', + password: 'testPassword', + id: 15 + }; + + const profileData = { + firstName: 'testFirstName', + lastName: 'testLastName' + }; + + def('subject', () => $subject.updateUserDetails(user, profileData, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('deleteUndefinedFieldsResponse', () => profileData); + def('updateDetailsResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(AppHelper, 'deleteUndefinedFields').returns($deleteUndefinedFieldsResponse); + $sandbox.stub(UserManager, 'updateDetails').returns($updateDetailsResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(profileData, Validator.schemas.updateUserProfile); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls AppHelper#deleteUndefinedFields() with correct args', async () => { + await $subject; + expect(AppHelper.deleteUndefinedFields).to.have.been.calledWith(profileData); + }); + + context('when AppHelper#deleteUndefinedFields() fails', () => { + def('deleteUndefinedFieldsResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('firstName'); + }) + }); + + context('when AppHelper#deleteUndefinedFields() succeeds', () => { + it('calls UserManager#updateDetails() with correct args', async () => { + await $subject; + expect(UserManager.updateDetails).to.have.been.calledWith(user, profileData, transaction); + }); + + context('when UserManager#updateDetails() fails', () => { + def('updateUserResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('firstName'); + }) + }); + + context('when UserManager#updateDetails() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('firstName'); + }) + }) + }) + }) + }); + + describe('.deleteUser()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + email: 'testEmail', + password: 'testPassword', + id: 15 + }; + + const profileData = { + firstName: 'testFirstName', + lastName: 'testLastName' + }; + + const force = false; + + def('subject', () => $subject.deleteUser(force, user, isCLI, transaction)); + def('findAllResponse', () => Promise.resolve([{}])); + def('deleteUserResponse', () => profileData); + + beforeEach(() => { + $sandbox.stub(ioFogManager, 'findAll').returns($findAllResponse); + $sandbox.stub(UserManager, 'delete').returns($deleteUserResponse); + }); + + it('calls ioFogManager#findAll() with correct args', async () => { + await $subject; + expect(ioFogManager.findAll).to.have.been.calledWith({ + userId: user.id + }, transaction); + }); + + context('when ioFogManager#findAll() fails', () => { + def('findAllResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ioFogManager#findAll() succeeds', () => { + it('calls UserManager#delete() with correct args', async () => { + await $subject; + expect(UserManager.delete).to.have.been.calledWith({ + id: user.id + }, transaction); + }); + + context('when UserManager#delete() fails', () => { + def('deleteUserResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + + context('when UserManager#delete() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined); + }) + }) + }) + }); + + // TODO updateUserPassword, resetUserPassword with rewire + + describe('.list()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const response = [{ + id: user.id + }]; + + def('subject', () => $subject.list(isCLI, transaction)); + def('findAllResponse', () => Promise.resolve(response)); + + beforeEach(() => { + $sandbox.stub(UserManager, 'findAll').returns($findAllResponse); + }); + + it('calls UserManager#findAll() with correct args', async () => { + await $subject; + expect(UserManager.findAll).to.have.been.calledWith({}, transaction); + }); + + context('when UserManager#findAll() fails', () => { + def('findAllResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when UserManager#findAll() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(response); + }) + }) + }); + + describe('.suspendUser()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const updatedObj = { + emailActivated: false + }; + + def('subject', () => $subject.suspendUser(user, isCLI, transaction)); + def('removeAccessTokenResponse', () => Promise.resolve()); + def('updateUserResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(AccessTokenService, 'removeAccessTokenByUserId').returns($removeAccessTokenResponse); + $sandbox.stub(UserManager, 'update').returns($updateUserResponse); + }); + + it('calls AccessTokenService#removeAccessTokenByUserId() with correct args', async () => { + await $subject; + expect(AccessTokenService.removeAccessTokenByUserId).to.have.been.calledWith(user.id, transaction); + }); + + context('when AccessTokenService#removeAccessTokenByUserId() fails', () => { + def('removeAccessTokenResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when AccessTokenService#removeAccessTokenByUserId() succeeds', () => { + it('calls UserManager#update() with correct args', async () => { + await $subject; + expect(UserManager.update).to.have.been.calledWith({ + id: user.id + }, updatedObj, transaction); + }); + + context('when UserManager#update() fails', () => { + def('removeAccessTokenResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when UserManager#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined); + }) + }) + }) + }); + +}); \ No newline at end of file From 43ff263224e47a1486f8e4641ac63a02914cd081 Mon Sep 17 00:00:00 2001 From: Railag Date: Fri, 25 Jan 2019 22:37:55 +0300 Subject: [PATCH 2/8] Release 1.0.34 (#514) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * 1.0.31 Release * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Release (#435) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Merge (#436) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release 1.1.0 [skip ci] * Update package.json * Release 1.1.0 [skip ci] * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * 1.0.31 Release (#448) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Release (#435) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Merge (#436) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release 1.1.0 [skip ci] * Update package.json * Release 1.1.0 [skip ci] * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * Release merge (#449) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Release (#435) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Merge (#436) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release 1.1.0 [skip ci] * Update package.json * Release 1.1.0 [skip ci] * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * 1.0.31 Release (#448) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Release (#435) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Merge (#436) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release 1.1.0 [skip ci] * Update package.json * Release 1.1.0 [skip ci] * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * Epankou/bug network containers not removed ewc 424 (#450) * EWC-418 added registry email validation * EWC-421 strace feature bug * EWC-421 strace feature bug fix * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * bug(fix) microservice removal: port mapping removal (EWC-424) * bug(fix) microservice removal: switched to const (EWC-424) * test(core) unit tests for agent service progress (EWC-383) (#452) * fix(cli): fix bug with generating access token for user in cli (#453) Closes EWC-443 * fix(cli): fix bug with generating access token for user in cli (EWC-453) * test(core) unit tests for agent-service (EWC-383) (#455) * bug(fix) fixed deprecated warning about Buffer constructor (EWC-422) * test(core) unit tests for catalog service (EWC-383) (#458) * Maksimchepelev/bugs (#457) * fix(cli): fix validation on delete connector Closes EWC-447 * fix(cli): fix data types and descriptions in help '... settings JSON file' -> 'Path to ... settings JSON file' flowId and catalogId type 'string' -> 'number' in help Closes EWC-445 EWC-446 * Maksimchepelev/bugs (#459) * fix(iofog): add validation for version command compare version command with isReadyToUpgrade and isReadyToRollback fields Closes EWC-448 * fix(code): fix logger is not defined error in app-helper Closes EWC-397 * test(core) unit tests for change-tracking service (EWC-383) (#460) * version 1.0.32 (#461) * Release 1.0.32 (#462) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * 1.0.31 Release (#448) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Release (#435) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Merge (#436) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release 1.1.0 [skip ci] * Update package.json * Release 1.1.0 [skip ci] * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * Epankou/bug network containers not removed ewc 424 (#450) * EWC-418 added registry email validation * EWC-421 strace feature bug * EWC-421 strace feature bug fix * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * bug(fix) microservice removal: port mapping removal (EWC-424) * bug(fix) microservice removal: switched to const (EWC-424) * test(core) unit tests for agent service progress (EWC-383) (#452) * fix(cli): fix bug with generating access token for user in cli (#453) Closes EWC-443 * test(core) unit tests for agent-service (EWC-383) (#455) * bug(fix) fixed deprecated warning about Buffer constructor (EWC-422) * test(core) unit tests for catalog service (EWC-383) (#458) * Maksimchepelev/bugs (#457) * fix(cli): fix validation on delete connector Closes EWC-447 * fix(cli): fix data types and descriptions in help '... settings JSON file' -> 'Path to ... settings JSON file' flowId and catalogId type 'string' -> 'number' in help Closes EWC-445 EWC-446 * Maksimchepelev/bugs (#459) * fix(iofog): add validation for version command compare version command with isReadyToUpgrade and isReadyToRollback fields Closes EWC-448 * fix(code): fix logger is not defined error in app-helper Closes EWC-397 * test(core) unit tests for change-tracking service (EWC-383) (#460) * version 1.0.32 (#461) * fix(iofog): add validation for version command (#463) * fix(iofog): add validation for version command compare version command with isReadyToUpgrade and isReadyToRollback fields Closes EWC-448 * fix(cli): fix data types and descriptions in help '... settings JSON file' -> 'Path to ... settings JSON file' flowId and catalogId type 'string' -> 'number' in help Closes EWC-445 EWC-446 * test(core) unit tests for connector & controller services (EWC-383) (#464) * test(core) unit tests for diagnostic service (EWC-383) (#465) * Epankou/bug route removal ewc 374 (#466) * EWC-418 added registry email validation * EWC-421 strace feature bug * EWC-421 strace feature bug fix * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * bug(fix) microservice removal: port mapping removal (EWC-424) * bug(fix) microservice removal: switched to const (EWC-424) * bug(fix) routes removal: added routes update on connector update (EWC-374) * bug(fix) routes removal: added routes update on connector update (EWC-374) * bug(fix) tests (EWC-374) * bug(fix) create connectorPortService (EWC-374) * bug(fix) tests (EWC-374) * bug(fix) refactoring (EWC-374) * test(core) unit tests for email activation service (EWC-383) (#468) * test(core) unit tests for flow service (EWC-383) (#469) * test(core) unit tests for iofog service (EWC-383) (#470) * Epankou/bug hal usb cli ewc 449 (#471) * EWC-418 added registry email validation * EWC-421 strace feature bug * EWC-421 strace feature bug fix * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * bug(fix) microservice removal: port mapping removal (EWC-424) * bug(fix) microservice removal: switched to const (EWC-424) * bug(fix) routes removal: added routes update on connector update (EWC-374) * bug(fix) routes removal: added routes update on connector update (EWC-374) * bug(fix) tests (EWC-374) * bug(fix) create connectorPortService (EWC-374) * bug(fix) tests (EWC-374) * bug(fix) refactoring (EWC-374) * bug(fix) usb hal info: fixed cli usb function (EWC-449) * version 1.0.33 (#472) * test(core) unit tests for microservices service (EWC-383) (#475) * test(core) unit tests for registry service (EWC-383) (#476) * test(core) unit tests for user service (EWC-383) (#478) * bug(fix) fixed connector update & microservice deletion (EWC-455) (EWC-447) bug(fix): fix update connector Closes EWC-455 * bug(fix): fix delete microservice Closes EWC-447 * feat(tests) Postman tests (EWC-442) * Maksimchepelev/bugs (#482) * fix(catalog): fix catalog list command for items without category + fix get by id Closes EWC-493 * fix(catalog): fix update catalog item allow update without registry Closes EWC-494 * bug(fix) agent deprovision improvement (EWC-440) * bug(fix) agent deprovision: unit tests for deprovision endpoint (EWC-440) * test(core) unit tests for app helper (EWC-381) (#483) * feat(flow): fix update flow * test(postman) updated postman collection (#485) * feat(catalog): fix update catalog item (EWC-495) * delete redundant logs in decorators * feat(catalog): fix update catalog item block update if running microservices exists Closes EWC-495 * feat(catalog): fix update catalog item fix test Closes EWC-495 * add prod env deployment (#488) * add step for postman tests * bug(fix) updating postman collection strace test (#490) * test(core) unit tests diagnostic and user services (EWC-452) * WIP: Add failure handle for postman tests (#486) * Add failure handle * Add exit code on failure * Add run summary * Update postmantest.js * update port * test ip instead of host * add step for postman test * Update .travis.yml * edit path to start script * edit npm command to run postman tests * add postman tests for dev and preprod env * edit build stage name * edit abort preferences * test to catch all test failures * add console error message * postman updates * Update postmantest.js * test(CLI) CLI script for controller smoke testing (EWC-419) (#492) bug(fix) CLI fixes (EWC-498) * Update .travis.yml * bug(fix): add arg type validation try to convert to number to get value type (EWC-501) * feat(core) CLI tests integration (#493) * fix(cli): fix critical error. correct comparison with NaN * feat(core) sentry crash reporting integration (EWC-453) * bug(fix) additional validation for iofog uuid in tunnel (EWC-498) (#496) * Add system items to catalog list (#498) * add system items to catalog list * remove system items from api * fix tests failing * bug(fix) updating CLI arguments formatting (EWC-508) * bug(fix) validation for registry on catalog item add (EWC-504) * bug(fix) fixing CLI output for tunnel (#501) * bug(fix) add custom error messages (EWC-500) * bug(fix) Add common format for ioFog node uuid parameter * fix(microservice): add ports volumeMappings and routes in info response (ENG-250) * 1.0.34 release * test travis ci build * Update .travis.yml * Update package.json * add branch checkout * CI check * version * bug(fix) CLI Catalog info/update fixes (ENG-542) * bug(fix) fixing deprecated buffer warning (ENG-540) * updating DSNs for Sentry crash reporting (#507) * merging --- .travis.yml | 16 +- package.json | 13 +- scripts/cli-tests.js | 420 ++++++++++++++++++ scripts/postmantest.js | 32 ++ src/cli/catalog.js | 21 +- src/cli/connector.js | 7 +- src/cli/diagnostics.js | 12 +- src/cli/flow.js | 15 +- src/cli/index.js | 7 + src/cli/iofog.js | 69 ++- src/cli/microservice.js | 83 ++-- src/cli/registry.js | 14 +- src/cli/tunnel.js | 10 +- src/cli/user.js | 19 +- src/config/default.json | 4 +- src/config/development.json | 4 +- src/config/production.json | 4 +- src/controllers/agent-controller.js | 21 +- src/decorators/authorization-decorator.js | 5 - src/decorators/cli-decorator.js | 2 - src/enums/fog-state.js | 19 + src/enums/microservice-state.js | 15 +- src/helpers/app-helper.js | 35 +- src/helpers/error-messages.js | 29 +- src/helpers/errors.js | 12 +- src/jobs/base/base-job-handler.js | 26 ++ src/jobs/fog-status-job.js | 72 +++ src/routes/agent.js | 48 +- src/schemas/agent.js | 15 +- src/schemas/index.js | 3 + src/schemas/microservice.js | 5 +- .../managers/microservice-manager.js | 5 +- src/sequelize/managers/strace-manager.js | 3 +- src/sequelize/managers/user-manager.js | 4 - .../managers/volume-mapping-manager.js | 1 - src/server.js | 47 +- src/services/agent-service.js | 37 +- src/services/catalog-service.js | 73 ++- src/services/connector-service.js | 14 +- src/services/diagnostic-service.js | 6 +- src/services/flow-service.js | 2 +- src/services/iofog-service.js | 142 +++--- src/services/microservices-service.js | 40 +- src/services/tunnel-service.js | 7 +- src/services/user-service.js | 5 +- ...ollection.json => postman_collection.json} | 44 +- test/src/controllers/agent-controller.test.js | 37 ++ test/src/helpers/app-helpers.test.js | 126 +++++- test/src/services/agent-service.test.js | 95 +++- test/src/services/catalog-service.test.js | 96 +++- test/src/services/diagnostic-service.test.js | 241 +++++----- test/src/services/flow-service.test.js | 2 +- test/src/services/iofog-service.test.js | 105 +---- .../services/microservices-service.test.js | 16 +- test/src/services/tunnel-service.test.js | 2 +- test/src/services/user-service.test.js | 160 ++++++- 56 files changed, 1725 insertions(+), 642 deletions(-) create mode 100644 scripts/cli-tests.js create mode 100644 scripts/postmantest.js create mode 100644 src/enums/fog-state.js create mode 100644 src/jobs/base/base-job-handler.js create mode 100644 src/jobs/fog-status-job.js rename test/{Controller Testing.postman_collection.json => postman_collection.json} (99%) diff --git a/.travis.yml b/.travis.yml index 7621a18e1..b554956fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,24 +18,28 @@ stages: if: type = pull_request - name: dev_deploy if: branch = develop AND type = push -- name: prod_deploy - if: branch = release AND type = push +- name: pre_release + if: branch =~ /^release-.*$/ AND type = push - name: release if: branch = master and type = push jobs: include: - stage: build + script: + - npm test + - NODE_ENV=production node /home/travis/build/ioFog/Controller/src/main.js start + - npm run postman_test - stage: dev_deploy before_install: - sudo apt-get install sshpass script: - - sshpass -p $DEV_MACHINE_PASSWORD ssh -o StrictHostKeyChecking=no $DEV_MACHINE_USERNAME@$DEV_MACHINE_IP "cd /FogController; NODE_ENV=production node src/main.js stop; git pull; npm i; NODE_ENV=production node src/main.js start" - - stage: prod_deploy + - sshpass -p $DEV_MACHINE_PASSWORD ssh -o StrictHostKeyChecking=no $DEV_MACHINE_USERNAME@$DEV_MACHINE_IP "cd /FogController; NODE_ENV=production node src/main.js stop; git pull; npm i; npm test; NODE_ENV=production node src/main.js start; npm run postman_test" + - stage: pre_release before_install: - sudo apt-get install sshpass script: - - sshpass -p $PROD_MACHINE_PASSWORD ssh -o StrictHostKeyChecking=no $PROD_MACHINE_USERNAME@$PROD_MACHINE_IP "cd /Controller; NODE_ENV=production node src/main.js stop; git pull; npm i; NODE_ENV=production node src/main.js start" + - sshpass -p $PREPROD_MACHINE_PASSWORD ssh -o StrictHostKeyChecking=no $PREPROD_MACHINE_USERNAME@$PREPROD_MACHINE_IP "cd /Controller; NODE_ENV=production node src/main.js stop; git pull; git checkout ${TRAVIS_BRANCH}; npm i; npm test; NODE_ENV=production node src/main.js start; npm run postman_test" - stage: release #before_install: #- git clone "https://github.com/$TRAVIS_REPO_SLUG.git" "$TRAVIS_REPO_SLUG"; @@ -54,3 +58,5 @@ jobs: api_key: ${NPM_AUTH_TOKEN} on: tags: false + after_deploy: + - sshpass -p $PROD_MACHINE_PASSWORD ssh -o StrictHostKeyChecking=no $PROD_MACHINE_USERNAME@$PROD_MACHINE_IP "iofog-controller stop; npm update -g iofogcontroller; iofog-controller start" diff --git a/package.json b/package.json index 2995967f4..079f5ab50 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.33", + "version": "1.0.34", "description": "ioFog Controller project for Eclipse IoFog @ iofog.org \\nCopyright (c) 2018 Edgeworx, Inc.", "main": "./src/main.js", "author": "Saeid Baghbidi", @@ -41,7 +41,9 @@ "postinstall": "node scripts/postinstall.js", "lint": "./node_modules/.bin/eslint \"**/*.js\"", "automatic-release": "automatic-release", - "test": "node scripts/test.js", + "test": "node scripts/test.js && node scripts/cli-tests.js", + "postman_test": "node scripts/postmantest.js", + "cli-tests": "node scripts/cli-tests.js", "coverage": "node scripts/coverage.js" }, "preferGlobal": true, @@ -80,7 +82,9 @@ "qs": "^6.5.2", "child_process": "^1.0.2", "os": "^0.1.1", - "semver": "^5.6.0" + "semver": "^5.6.0", + "newman": "^4.3.1", + "@sentry/node": "^4.5.0" }, "devDependencies": { "automatic-release": "^1.1.1", @@ -92,6 +96,7 @@ "mocha": "^5.2.0", "nyc": "^13.1.0", "sinon": "^7.1.1", - "sinon-chai": "^3.2.0" + "sinon-chai": "^3.2.0", + "newman": "^4.3.1" } } diff --git a/scripts/cli-tests.js b/scripts/cli-tests.js new file mode 100644 index 000000000..04e97d0a3 --- /dev/null +++ b/scripts/cli-tests.js @@ -0,0 +1,420 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2018 Edgeworx, Inc. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const execSync = require('child_process').execSync; + +const options = { + env: { + 'NODE_ENV': 'production', + "PATH": process.env.PATH + } +}; + +let testsCounter = 0; +let testsFailed = 0; + +const controllerStatusFields = ['status', 'timestamp']; +const controllerEmailActivationFields = ['isEmailActivationEnabled']; +const controllerFogTypesFields = ['fogTypes']; + +const userCreateFields = ['id']; +const userAccessTokenFields = ['accessToken']; + +const ioFogCreateFields = ['uuid']; +const ioFogListFields = ['fogs']; +const ioFogProvisioningFields = ['key', 'expirationTime']; + +const catalogCreateFields = ['id']; +const catalogListFields = ['catalogItems']; + +const flowCreateFields = ['id']; +const flowListFields = ['flows']; + +const microserviceCreateFields = ['uuid']; +const microserviceListFields = ['microservices']; + +const volumeMappingCreateFields = ['id']; + +const registryCreateFields = ['id']; +const registryListFields = ['registries']; + +const tunnelListFields = ['tunnels']; + +function testControllerSection() { + console.log("\n=============================\nStarting controller section.."); + + responseHasFields(testCommand('controller status'), controllerStatusFields); + responseHasFields(testCommand('controller email-activation'), controllerEmailActivationFields); + responseHasFields(testCommand('controller fog-types'), controllerFogTypesFields); + hasSomeResponse(testCommand('controller version')); +} + +function testUserSection() { + console.log("\n=============================\nStarting user section.."); + + responseHasFields(testCommand("user add -f John -l Doe -e user@domain.com -p '#Bugs4Fun'"), userCreateFields); + responseEquals(testCommand('user update -f John2 -l Doe2 -e user@domain.com -p \'#Bugs4Fun34\''), + 'User updated successfully.'); + responseIsArray(testCommand('user list')); + responseHasFields(testCommand('user generate-token -e user@domain.com'), userAccessTokenFields); + responseEquals(testCommand('user suspend -e user@domain.com'), 'User suspended successfully.'); + responseEquals(testCommand('user activate -e user@domain.com'), 'User activated successfully.'); + responseEquals(testCommand('user remove -e user@domain.com'), 'User removed successfully.'); +} + +function testConfigSection() { + console.log("\n=============================\nStarting config section.."); + + // TODO backup config before this command + // hasSomeResponse(testCommand("config add -p 1234 -c testPath -k testSslPath -i testIntermediateCertPath" + + // " -h testHomeUrl -a testEmailAddress -w testEmailPassword -s testEmailService -d testLogDir -z 555")); + hasSomeResponse(testCommand('config list')); + responseEquals(testCommand('config dev-mode -o'), 'Dev mode state updated successfully.'); + responseEquals(testCommand('config email-activation -f'), 'Email activation state updated successfully.'); +} + +function testConnectorSection() { + console.log("\n=============================\nStarting connector section.."); + + responseContains(testCommand("connector add -i 127.0.0.1 -n Connector1 -d iofog.test.org -c testCertPath" + + " -s -H"), 'Connector has been created successfully.'); + responseEquals(testCommand('connector update -i 127.0.0.1 -n Connector2 -d iofog.test.org -c testCertPath' + + ' -s -H'), 'Connector has been updated successfully.'); + responseEquals(testCommand('connector remove -i 127.0.0.1'), 'Connector has been removed successfully.'); + responseIsArray(testCommand('connector list')); +} + +function testTunnelSection() { + console.log("\n=============================\nStarting tunnel section.."); + + responseContains(testCommand('tunnel update -i testIoFogUuid -u testUsername -p testPassword -s 127.0.0.1 ' + + '-k testRSAKeyPath -o 2048 -a open'), 'ENOENT: no such file or directory'); + responseHasFields(testCommand('tunnel list'), tunnelListFields); +} + +function testIoFogSection() { + console.log("\n=============================\nStarting iofog section.."); + + const userCreateResponse = responseHasFields(executeCommand("user add -f John -l Doe -e fogUser@domain.com" + + " -p '#Bugs4Fun'"), userCreateFields); + const userId = userCreateResponse.id; + + try { + const ioFogCreateResponse = responseHasFields(testCommand("iofog add -n ioFog1 -l testLocation -t 55 -g 65" + + " -d testDescription -D testDockerUrl -M 55 -T testDiskDirectoryString -m 65 -c 24 -G 1 -Y testLogDirectory " + + "-C 15 -s 25 -F 27 -Q 26 -B -W -A -y 1 -u " + userId), ioFogCreateFields); + const ioFogUuid = ioFogCreateResponse.uuid; + responseEquals(testCommand("iofog update -i " + ioFogUuid + " -n ioFog1 -l testLocation -t 55 -g 65 " + + "-d testDescription -D testDockerUrl -M 55 -T testDiskDirectoryString -m 65 -c 24 -G 1 -Y testLogDirectory " + + "-C 15 -s 25 -F 27 -Q 26 -B -W -A -y 1"), 'ioFog node has been updated successfully.'); + responseHasFields(testCommand('iofog list'), ioFogListFields); + responseHasFields(testCommand('iofog info -i ' + ioFogUuid), ioFogCreateFields); + responseHasFields(testCommand('iofog provisioning-key -i ' + ioFogUuid), ioFogProvisioningFields); + responseEquals(testCommand('iofog reboot -i ' + ioFogUuid), 'ioFog reboot command has been set successfully'); + responseEquals(testCommand('iofog version -i ' + ioFogUuid + ' -v upgrade'), + 'ioFog version command has been set successfully'); + hasSomeResponse(testCommand('iofog hal-hw -i ' + ioFogUuid)); + hasSomeResponse(testCommand('iofog hal-usb -i ' + ioFogUuid)); + responseEquals(testCommand('iofog remove -i ' + ioFogUuid), 'ioFog node has been removed successfully'); + executeCommand('user remove -e fogUser@domain.com'); + } catch (exception) { + executeCommand('user remove -e fogUser@domain.com'); + } +} + +function testCatalogSection() { + console.log("\n=============================\nStarting catalog section.."); + + const userCreateResponse = responseHasFields(executeCommand("user add -f John -l Doe -e catalogUser@domain.com" + + " -p '#Bugs4Fun'"), userCreateFields); + const userId = userCreateResponse.id; + const registryCreateResponse = responseHasFields(executeCommand("registry add -U testRegistryUri -b -l testUserName" + + " -p testPassword -e testEmail@gmail.com -u " + userId), registryCreateFields); + const registryId = registryCreateResponse.id; + + try { + const catalogCreateResponse = responseHasFields(testCommand("catalog add -n testCatalogItem1 -d testDescription" + + " -c testCategory -x testIntelImage -a testArmImage -p testPublisher -s 15 -r 15 -t testPicture -g " + + registryId + " -I testInputType -F testInputFormat -O testOutputType -T testOutputFormat " + + "-X '{}' -u " + userId), catalogCreateFields); + const catalogId = catalogCreateResponse.id; + responseEquals(testCommand("catalog update -i " + catalogId + " -n testCatalogItem2 -d testDescription" + + " -c testCategory -x testIntelImage -a testArmImage -p testPublisher -s 15 -r 15 -t testPicture -g " + + registryId + " -I testInputType -F testInputFormat -O testOutputType -T testOutputFormat -X '{}'"), + 'Catalog item has been updated successfully.'); + responseHasFields(testCommand('catalog list'), catalogListFields); + responseHasFields(testCommand('catalog info -i ' + catalogId), catalogCreateFields); + responseEquals(testCommand('catalog remove -i ' + catalogId), 'Catalog item has been removed successfully'); + executeCommand('registry remove -i ' + registryId); + executeCommand('user remove -e catalogUser@domain.com'); + } catch (exception) { + executeCommand('registry remove -i ' + registryId); + executeCommand('user remove -e catalogUser@domain.com'); + } +} + +function testFlowSection() { + console.log("\n=============================\nStarting flow section.."); + + const userCreateResponse = responseHasFields(executeCommand("user add -f John -l Doe -e flowUser@domain.com" + + " -p '#Bugs4Fun'"), userCreateFields); + const userId = userCreateResponse.id; + + try { + const flowCreateResponse = responseHasFields(testCommand("flow add -n testFlow1 -d testDescription" + + " -a -u " + userId), flowCreateFields); + const flowId = flowCreateResponse.id; + responseEquals(testCommand("flow update -i " + flowId + " -n testFlow1 -d testDescription -a"), + 'Flow updated successfully.'); + responseHasFields(testCommand('flow list'), flowListFields); + responseHasFields(testCommand('flow info -i ' + flowId), flowCreateFields); + responseEquals(testCommand('flow remove -i ' + flowId), 'Flow removed successfully.'); + executeCommand('user remove -e flowUser@domain.com'); + } catch (exception) { + executeCommand('user remove -e flowUser@domain.com'); + } +} + +function testMicroserviceSection() { + console.log("\n=============================\nStarting microservice section.."); + + const userCreateResponse = responseHasFields(executeCommand("user add -f John -l Doe -e microserviceUser@domain.com" + + " -p '#Bugs4Fun'"), userCreateFields); + const userId = userCreateResponse.id; + + const registryCreateResponse = responseHasFields(executeCommand("registry add -U testRegistryUri -b -l testUserName" + + " -p testPassword -e testEmail@gmail.com -u " + userId), registryCreateFields); + const registryId = registryCreateResponse.id; + + const catalogCreateResponse = responseHasFields(executeCommand("catalog add -n testCatalogItem1 -d testDescription" + + " -c testCategory -x testIntelImage -a testArmImage -p testPublisher -s 15 -r 15 -t testPicture -g " + + registryId + " -I testInputType -F testInputFormat -O testOutputType -T testOutputFormat " + + "-X '{}' -u " + userId), catalogCreateFields); + const catalogId = catalogCreateResponse.id; + + const flowCreateResponse = responseHasFields(executeCommand("flow add -n testFlow1 -d testDescription" + + " -a -u " + userId), flowCreateFields); + const flowId = flowCreateResponse.id; + + const ioFogCreateResponse = responseHasFields(executeCommand("iofog add -n ioFog1 -l testLocation -t 55 -g 65 " + + "-d testDescription -D testDockerUrl -M 55 -T testDiskDirectoryString -m 65 -c 24 -G 1 -Y testLogDirectory " + + "-C 15 -s 25 -F 27 -Q 26 -B -W -A -y 1 -u " + userId), ioFogCreateFields); + const ioFogUuid = ioFogCreateResponse.uuid; + + try { + const microserviceCreateResponse = responseHasFields(testCommand("microservice add -n microserviceName1" + + " -c " + catalogId + " -F " + flowId + " -I " + ioFogUuid + " -g '{}' -v /host_src:/container_src:rw -l 15 -R" + + " -p 80:8080:false -u " + userId), microserviceCreateFields); + const microserviceUuid = microserviceCreateResponse.uuid; + responseEquals(testCommand("microservice update -i " + microserviceUuid + " -n microserviceName2" + + " -I " + ioFogUuid + " -g '{}' -v /host_src:/container_src:rw -l 15 -R -w"), + 'Microservice has been updated successfully.'); + responseHasFields(testCommand('microservice list'), microserviceListFields); + responseHasFields(testCommand('microservice info -i ' + microserviceUuid), microserviceCreateFields); + responseContains(testCommand('microservice route-create -T ' + microserviceUuid + ':' + microserviceUuid), + 'has been created successfully'); + responseContains(testCommand('microservice route-remove -T ' + microserviceUuid + ':' + microserviceUuid), + 'has been removed successfully'); + responseContains(testCommand('microservice port-mapping-create -i ' + microserviceUuid + ' -P 90:9090:false'), + 'Port mapping has been created successfully.'); + responseIsArray(testCommand('microservice port-mapping-list -i ' + microserviceUuid)); + responseEquals(testCommand('microservice port-mapping-remove -i ' + microserviceUuid + ' -b 90'), + 'Port mapping has been removed successfully.'); + const volumeMappingCreateResponse = responseHasFields(testCommand('microservice volume-mapping-create' + + ' -i ' + microserviceUuid + ' -P /test_path:/container_test_path:rw'), volumeMappingCreateFields); + const volumeMappingId = volumeMappingCreateResponse.id; + responseIsArray(testCommand('microservice volume-mapping-list -i ' + microserviceUuid)); + responseContains(testCommand('microservice volume-mapping-remove -i ' + microserviceUuid + ' -a ' + volumeMappingId), + 'Volume mapping has been deleted successfully.'); + responseEquals(testCommand('microservice remove -i ' + microserviceUuid), + 'Microservice has been removed successfully.'); + executeCommand('iofog remove -i ' + ioFogUuid); + executeCommand('flow remove -i ' + flowId); + executeCommand('catalog remove -i ' + catalogId); + executeCommand('user remove -e microserviceUser@domain.com'); + } catch (exception) { + executeCommand('iofog remove -i ' + ioFogUuid); + executeCommand('flow remove -i ' + flowId); + executeCommand('catalog remove -i ' + catalogId); + executeCommand('registry remove -i ' + registryId); + executeCommand('user remove -e microserviceUser@domain.com'); + } +} + +function testRegistrySection() { + console.log("\n=============================\nStarting registry section.."); + + const userCreateResponse = responseHasFields(executeCommand("user add -f John -l Doe -e registryUser@domain.com" + + " -p '#Bugs4Fun'"), userCreateFields); + + try { + const userId = userCreateResponse.id; + const registryCreateResponse = responseHasFields(testCommand("registry add -U testRegistryUri -b -l testUserName" + + " -p testPassword -e testEmail@gmail.com -u " + userId), registryCreateFields); + const registryId = registryCreateResponse.id; + responseEquals(testCommand("registry update -i " + registryId + " -U testRegistryUri -b -l testUserName" + + " -p testPassword -e testEmail@gmail.com"), 'Registry has been updated successfully.'); + responseHasFields(testCommand('registry list'), registryListFields); + responseEquals(testCommand('registry remove -i ' + registryId), 'Registry has been removed successfully.'); + executeCommand('user remove -e registryUser@domain.com'); + } catch (exception) { + executeCommand('user remove -e registryUser@domain.com'); + } +} + +function testDiagnosticsSection() { + console.log("\n=============================\nStarting diagnostics section.."); + + const userCreateResponse = responseHasFields(executeCommand("user add -f John -l Doe -e diagnosticsUser@domain.com" + + " -p '#Bugs4Fun'"), userCreateFields); + const userId = userCreateResponse.id; + + const registryCreateResponse = responseHasFields(executeCommand("registry add -U testRegistryUri -b -l testUserName" + + " -p testPassword -e testEmail@gmail.com -u " + userId), registryCreateFields); + const registryId = registryCreateResponse.id; + + const catalogCreateResponse = responseHasFields(executeCommand("catalog add -n testCatalogItem1 -d testDescription" + + " -c testCategory -x testIntelImage -a testArmImage -p testPublisher -s 15 -r 15 -t testPicture -g " + + registryId + " -I testInputType -F testInputFormat -O testOutputType -T testOutputFormat " + + "-X '{}' -u " + userId), catalogCreateFields); + const catalogId = catalogCreateResponse.id; + + const flowCreateResponse = responseHasFields(executeCommand("flow add -n testFlow1 -d testDescription" + + " -a -u " + userId), flowCreateFields); + const flowId = flowCreateResponse.id; + + const ioFogCreateResponse = responseHasFields(executeCommand("iofog add -n ioFog1 -l testLocation -t 55 -g 65" + + " -d testDescription -D testDockerUrl -M 55 -T testDiskDirectoryString -m 65 -c 24 -G 1 -Y testLogDirectory " + + "-C 15 -s 25 -F 27 -Q 26 -B -W -A -y 1 -u " + userId), ioFogCreateFields); + const ioFogUuid = ioFogCreateResponse.uuid; + + const microserviceCreateResponse = responseHasFields(executeCommand("microservice add -n microserviceName1" + + " -c " + catalogId + " -F " + flowId + " -I " + ioFogUuid + " -g '{}' -v /host_src:/container_src:rw -l 15 -R" + + " -p 80:8080:false -u " + userId), microserviceCreateFields); + const microserviceUuid = microserviceCreateResponse.uuid; + + try { + responseEquals(testCommand("diagnostics strace-update -e -i " + microserviceUuid), + 'Microservice strace has been enabled'); + responseContains(testCommand('diagnostics strace-info -f string -i ' + microserviceUuid), + 'Microservice strace data has been retrieved successfully.'); + responseContains(testCommand('diagnostics strace-ftp-post -i ' + microserviceUuid + ' -h ftpTestHost -p 2024' + + ' -u testFtpUser -s testFtpPass -d ftpTestDestination'), 'FTP error'); + responseContains(testCommand('diagnostics image-snapshot-create -i ' + microserviceUuid), + 'Microservice image snapshot has been created successfully.'); + responseContains(testCommand('diagnostics image-snapshot-get -i ' + microserviceUuid), + 'Image snapshot is not available for this microservice.'); + executeCommand('microservice remove -i ' + microserviceUuid); + executeCommand('iofog remove -i ' + ioFogUuid); + executeCommand('flow remove -i ' + flowId); + executeCommand('catalog remove -i ' + catalogId); + executeCommand('registry remove -i ' + registryId); + executeCommand('user remove -e diagnosticsUser@domain.com'); + } catch (exception) { + executeCommand('microservice remove -i ' + microserviceUuid); + executeCommand('iofog remove -i ' + ioFogUuid); + executeCommand('flow remove -i ' + flowId); + executeCommand('catalog remove -i ' + catalogId); + executeCommand('registry remove -i ' + registryId); + executeCommand('user remove -e diagnosticsUser@domain.com'); + } +} + +function testCommand(command) { + console.log("\n Testing command '" + command + "'"); + testsCounter++; + return executeCommand(command); +} + +function executeCommand(command) { + let response = execSync('node ./src/main.js ' + command, options); + response = response.toString(); + response = response.replace(/\r?\n?/g, ''); // remove line breaks + return response; +} + +function hasSomeResponse(response) { + if (response === undefined || response === null) { + testsFailed++; + console.log("'hasSomeResponse' test failed with response: " + JSON.stringify(response)); + } +} + +function responseIsArray(jsonResponse) { + try { + const response = JSON.parse(jsonResponse); + if (!Array.isArray(response)) { + testsFailed++; + console.log("'responseIsArray' test failed with response: " + JSON.stringify(response)); + } + } catch (exception) { + testsFailed++; + console.log("'responseIsArray' test failed due to invalid JSON with response: " + JSON.stringify(jsonResponse)); + } +} + +function responseHasFields(jsonResponse, fields) { + try { + const response = JSON.parse(jsonResponse); + for (const field of fields) { + if (!response.hasOwnProperty(field)) { + testsFailed++; + console.log("'responseHasFields' test failed with response: " + JSON.stringify(response)); + } + } + + return response; + } catch (exception) { + testsFailed++; + console.log("'responseHasFields' test failed due to invalid JSON with response: " + JSON.stringify(jsonResponse)); + } +} + +function responseEquals(response, expectedResponse) { + if (response !== expectedResponse) { + testsFailed++; + console.log("'responseEquals' test failed with response: " + JSON.stringify(response)); + } +} + +function responseContains(response, expectedResponsePart) { + if (!response.includes(expectedResponsePart)) { + testsFailed++; + console.log("'responseContains' test failed with response: " + JSON.stringify(response)); + } +} + +try { + testControllerSection(); + testUserSection(); + testConfigSection(); + testConnectorSection(); + testTunnelSection(); + testIoFogSection(); + testCatalogSection(); + testFlowSection(); + testMicroserviceSection(); + testRegistrySection(); + testDiagnosticsSection(); +} catch (exception) { + console.log("\nException during execution: "); + console.error(exception); + process.exit(1); +} + +if (testsFailed > 0) { + console.log("\nFailed tests count: " + testsFailed); + process.exit(1); +} else { + console.log("\nCLI Tests passed successfully."); +} \ No newline at end of file diff --git a/scripts/postmantest.js b/scripts/postmantest.js new file mode 100644 index 000000000..b3979329c --- /dev/null +++ b/scripts/postmantest.js @@ -0,0 +1,32 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2018 Edgeworx, Inc. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + + const newman = require('newman'); + +// call newman.run to pass `options` object and wait for callback +newman.run({ + collection: require('../test/postman_collection.json'), + reporters: 'cli', + //abortOnError: true, + //abortOnFailure: true +}).on('start', function (err, args) { // on start of run, log to console + console.log('running a collection...'); +}).on('done', function (err, summary) { + if (err || summary.error || summary.run.failures.length != 0) { + console.error('collection run encountered an error. tests did not pass.'); + process.exitCode = 1; + } + else { + console.log('collection run completed.'); + } +}); diff --git a/src/cli/catalog.js b/src/cli/catalog.js index 7d83d7e76..07d5c03b4 100644 --- a/src/cli/catalog.js +++ b/src/cli/catalog.js @@ -18,6 +18,8 @@ const CatalogItemService = require('../services/catalog-service'); const fs = require('fs'); const AppHelper = require('../helpers/app-helper'); const AuthDecorator = require('../decorators/cli-decorator'); +const Errors = require('../helpers/errors'); +const ErrorMessages = require('../helpers/error-messages'); const JSON_SCHEMA = AppHelper.stringifyCliJsonSchema({ name: "string", @@ -214,11 +216,10 @@ const _createCatalogItem = async function (obj, user) { ? JSON.parse(fs.readFileSync(obj.file, 'utf8')) : _createCatalogItemObject(obj); - logger.info(JSON.stringify(item)); - - const result = await CatalogItemService.createCatalogItem(item, user); - logger.info(JSON.stringify(result)); - logger.info('Catalog item has been created successfully.'); + const catalogItemIdObject = await CatalogItemService.createCatalogItem(item, user); + logger.info(JSON.stringify({ + id: catalogItemIdObject.id + }, null, 2)); }; const _updateCatalogItem = async function (obj) { @@ -226,14 +227,15 @@ const _updateCatalogItem = async function (obj) { ? JSON.parse(fs.readFileSync(obj.file, 'utf8')) : _createCatalogItemObject(obj); - logger.info('Item id: ' + obj.itemId); - logger.info(JSON.stringify(item)); + if (obj.itemId === undefined) { + throw new Errors.NotFoundError(ErrorMessages.CATALOG_UPDATE_REQUIRES_ID); + } + await CatalogItemService.updateCatalogItem(obj.itemId, item, {}, true); logger.info('Catalog item has been updated successfully.'); }; const _deleteCatalogItem = async function (obj) { - logger.info(JSON.stringify(obj)); await CatalogItemService.deleteCatalogItem(obj.itemId, {}, true); logger.info('Catalog item has been removed successfully'); }; @@ -241,14 +243,11 @@ const _deleteCatalogItem = async function (obj) { const _listCatalogItems = async function () { const result = await CatalogItemService.listCatalogItems({}, true); logger.info(JSON.stringify(result, null, 2)); - logger.info('Catalog items have been successfully retrieved.'); }; const _listCatalogItem = async function (obj) { - logger.info(JSON.stringify(obj)); const result = await CatalogItemService.getCatalogItem(obj.itemId, {}, true); logger.info(JSON.stringify(result, null, 2)); - logger.info('Catalog item has been successfully retrieved.'); }; const _createCatalogItemObject = function (catalogItem) { diff --git a/src/cli/connector.js b/src/cli/connector.js index 1fbcbafa6..0839fd3ba 100644 --- a/src/cli/connector.js +++ b/src/cli/connector.js @@ -127,10 +127,8 @@ async function _executeCase(commands, commandName, f, isUserRequired) { async function _createConnector(obj) { const connector = _createConnectorObject(obj); - logger.info(JSON.stringify(connector)); try { - const result = await ConnectorService.createConnector(connector); - logger.info(JSON.stringify(result)); + await ConnectorService.createConnector(connector); logger.info('Connector has been created successfully.'); } catch (e) { logger.info(e.message) @@ -139,7 +137,6 @@ async function _createConnector(obj) { async function _updateConnector(obj) { const connector = _createConnectorObject(obj); - logger.info(JSON.stringify(connector)); try { await ConnectorService.updateConnector(connector); logger.info('Connector has been updated successfully.'); @@ -150,7 +147,6 @@ async function _updateConnector(obj) { async function _deleteConnector(obj) { const connector = _createConnectorObject(obj); - logger.info(JSON.stringify(connector)); try { await ConnectorService.deleteConnector(connector); logger.info('Connector has been removed successfully.'); @@ -162,7 +158,6 @@ async function _deleteConnector(obj) { async function _getConnectorList() { const list = await ConnectorService.getConnectorList(); logger.info(JSON.stringify(list, null, 2)); - logger.info('Connector list has been gotten successfully'); } function _createConnectorObject(cliData) { diff --git a/src/cli/diagnostics.js b/src/cli/diagnostics.js index 1a0445f3d..dd3ab2593 100644 --- a/src/cli/diagnostics.js +++ b/src/cli/diagnostics.js @@ -126,8 +126,6 @@ const _executeCase = async function (diagnosticCommand, commandName, f, isUserRe }; const _changeMicroserviceStraceState = async function (obj) { - logger.info(JSON.stringify(obj)); - const isEnable = AppHelper.validateBooleanCliOptions(obj.enable, obj.disable); await DiagnosticService.changeMicroserviceStraceState(obj.microserviceUuid, {enable: isEnable}, {}, true); const msg = isEnable ? 'Microservice strace has been enabled' : 'Microservice strace has been disabled'; @@ -135,8 +133,6 @@ const _changeMicroserviceStraceState = async function (obj) { }; const _getMicroserviceStraceData = async function (obj) { - logger.info(JSON.stringify(obj)); - const result = await DiagnosticService.getMicroserviceStraceData(obj.microserviceUuid, {format: obj.format}, {}, true); logger.info('Strace data:'); logger.info('============================='); @@ -145,22 +141,16 @@ const _getMicroserviceStraceData = async function (obj) { }; const _postMicroserviceStraceDataToFtp = async function (obj) { - logger.info(JSON.stringify(obj)); - await DiagnosticService.postMicroserviceStraceDatatoFtp(obj.microserviceUuid, obj, {}, true); - logger.info('Strace data has been posted to ftp successfully.'); + logger.info('Strace data has been posted to FTP successfully.'); }; const _postMicroserviceImageSnapshotCreate = async function (obj) { - logger.info(JSON.stringify(obj)); - await DiagnosticService.postMicroserviceImageSnapshotCreate(obj.microserviceUuid, {}, true); logger.info('Microservice image snapshot has been created successfully.'); }; const _getMicroserviceImageSnapshot = async function (obj) { - logger.info(JSON.stringify(obj)); - const filePath = await DiagnosticService.getMicroserviceImageSnapshot(obj.microserviceUuid, {}, true); logger.info('Microservice images path = ' + filePath); }; diff --git a/src/cli/flow.js b/src/cli/flow.js index 5c7a718c4..e61cfc9fb 100644 --- a/src/cli/flow.js +++ b/src/cli/flow.js @@ -146,10 +146,10 @@ const _createFlow = async function (flowData, user) { ? JSON.parse(fs.readFileSync(flowData.file, 'utf8')) : _createFlowObject(flowData); - logger.info(JSON.stringify(flow)); - - await FlowService.createFlow(flow, user, true); - logger.info('Flow created successfully.'); + const createdFlow = await FlowService.createFlow(flow, user, true); + logger.info(JSON.stringify({ + id: createdFlow.id + }, null, 2)); }; const _updateFlow = async function (flowData) { @@ -157,7 +157,6 @@ const _updateFlow = async function (flowData) { ? JSON.parse(fs.readFileSync(flowData.file, 'utf8')) : _createFlowObject(flowData); - logger.info(JSON.stringify(flow)); const flowId = flowData.flowId; await FlowService.updateFlow(flow, flowId, {}, true); @@ -165,8 +164,6 @@ const _updateFlow = async function (flowData) { }; const _deleteFlow = async function (flowData) { - logger.info(JSON.stringify(flowData)); - const flowId = flowData.flowId; await FlowService.deleteFlow(flowId, {}, true); @@ -176,17 +173,13 @@ const _deleteFlow = async function (flowData) { const _getAllFlows = async function () { const flows = await FlowService.getAllFlows(true); logger.info(JSON.stringify(flows, null, 2)); - logger.info('All flows have been retrieved successfully.'); }; const _getFlow = async function (flowData) { - logger.info(JSON.stringify(flowData)); - const flowId = flowData.flowId; const flow = await FlowService.getFlowWithTransaction(flowId, {}, true); logger.info(JSON.stringify(flow, null, 2)); - logger.info(`Flow with id ${flowId} has been retrieved successfully.`) }; function _createFlowObject(data) { diff --git a/src/cli/index.js b/src/cli/index.js index 9afa05773..2b43c297f 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -24,9 +24,16 @@ const Microservice = require('./microservice'); const Registry = require('./registry'); const Controller = require('./controller'); const Diagnostics = require('./diagnostics'); +const packageJson = require('./../../package'); const constants = require('../helpers/constants'); +const Sentry = require('@sentry/node'); +Sentry.init({ dsn: 'https://3213bc0b88db47ffb103075d7e1e254f@sentry.io/1378606' }); +Sentry.configureScope(scope => { + scope.setExtra('version', packageJson.version); +}); + class Cli extends BaseCLIHandler { constructor() { super(); diff --git a/src/cli/iofog.js b/src/cli/iofog.js index 5a7606587..b328d5e2d 100644 --- a/src/cli/iofog.js +++ b/src/cli/iofog.js @@ -50,15 +50,16 @@ class IOFog extends BaseCLIHandler { this.commandDefinitions = [ { name: 'command', defaultOption: true, - group: [constants.CMD]}, + group: [constants.CMD] + }, { name: 'file', alias: 'f', type: String, description: 'Path to ioFog settings JSON file', group: [constants.CMD_ADD, constants.CMD_UPDATE] }, { - name: 'node-id', alias: 'i', type: String, - description: 'ioFog node ID', + name: 'iofog-uuid', alias: 'i', type: String, + description: 'ioFog node UUID', group: [constants.CMD_UPDATE, constants.CMD_REMOVE, constants.CMD_INFO, constants.CMD_PROVISIONING_KEY, constants.CMD_IOFOG_REBOOT, constants.CMD_VERSION, constants.CMD_HAL_HW, constants.CMD_HAL_USB] }, @@ -287,11 +288,10 @@ async function _createFog(obj, user) { ? JSON.parse(fs.readFileSync(obj.file, 'utf8')) : _createFogObject(obj); - logger.info(JSON.stringify(fog)); - const result = await FogService.createFog(fog, user, true); - logger.info(JSON.stringify(result)); - logger.info('Fog has been created successfully.'); + logger.info(JSON.stringify({ + uuid: result.uuid + }, null, 2)); } async function _updateFog(obj, user) { @@ -299,92 +299,85 @@ async function _updateFog(obj, user) { ? JSON.parse(fs.readFileSync(obj.file, 'utf8')) : _createFogObject(obj); - fog.uuid = obj.nodeId - logger.info(JSON.stringify(fog)); + fog.uuid = obj.iofogUuid; await FogService.updateFog(fog, user, true); - logger.info('Fog has been updated successfully.'); + logger.info('ioFog node has been updated successfully.'); } async function _deleteFog(obj, user) { const fog = _createFogObject(obj); - logger.info(JSON.stringify(fog)); await FogService.deleteFog(fog, user, true); - logger.info('Fog has been removed successfully'); + logger.info('ioFog node has been removed successfully'); } async function _getFogList(obj, user) { const emptyFilters = []; const list = await FogService.getFogList(emptyFilters, user, true); logger.info(JSON.stringify(list, null, 2)); - logger.info('Fog list has been gotten successfully.'); } async function _getFog(obj, user) { const fog = _createFogObject(obj); const res = await FogService.getFogWithTransaction(fog, user, true); logger.info(JSON.stringify(res, null, 2)); - logger.info('Fog has been gotten successfully.'); } async function _generateProvision(obj, user) { const fog = _createFogObject(obj); - logger.info(JSON.stringify(fog)); - const res = await FogService.generateProvisioningKey(fog, user, true); - logger.info('Provisioning key: ' + JSON.stringify(res, null, 2)); - logger.info('Fog provisioning key has been generated successfully.'); + const response = await FogService.generateProvisioningKey(fog, user, true); + logger.info(JSON.stringify(response), null, 2); } async function _setFogRebootCommand(obj, user) { const fog = _createFogObject(obj); - logger.info(JSON.stringify(fog)); await FogService.setFogRebootCommand(fog, user, true); - logger.info('Fog reboot command has been set successfully'); + logger.info('ioFog reboot command has been set successfully'); } async function _setFogVersionCommand(obj, user) { const fog = { - uuid: obj.nodeId, + uuid: obj.iofogUuid, versionCommand: obj.versionCommand }; - logger.info(JSON.stringify(fog)); await FogService.setFogVersionCommand(fog, user, true); - logger.info('Fog version command has been set successfully'); + logger.info('ioFog version command has been set successfully'); } async function _getHalHardwareInfo(obj) { const uuidObj = { - uuid: obj.nodeId + uuid: obj.iofogUuid }; - logger.info("Parameters" + JSON.stringify(uuidObj)); - const data = await FogService.getHalHardwareInfo(uuidObj, {}, true); - if (data.info) { - data.info = JSON.parse(data.info); + if (data) { + if (data.hasOwnProperty('info')) { + data.info = JSON.parse(data.info); + } + + logger.info(JSON.stringify(data, null, 2)); } - logger.info(JSON.stringify(data, null, 2)); - logger.info('Hardware info has been retrieved successfully.') + } async function _getHalUsbInfo(obj) { const uuidObj = { - uuid: obj.nodeId + uuid: obj.iofogUuid }; - logger.info("Parameters" + JSON.stringify(uuidObj)); - const data = await FogService.getHalUsbInfo(uuidObj, {}, true); - if (data.info) { - data.info = JSON.parse(data.info); + if (data) { + if (data.hasOwnProperty('info')) { + data.info = JSON.parse(data.info); + } + + logger.info(JSON.stringify(data, null, 2)); } - logger.info(JSON.stringify(data, null, 2)); - logger.info('Usb info has been retrieved successfully.') } function _createFogObject(cliData) { const fogObj = { - uuid: cliData.nodeId, + uuid: cliData.iofogUuid, name: cliData.name, location: cliData.location, latitude: cliData.latitude, diff --git a/src/cli/microservice.js b/src/cli/microservice.js index 812e63474..fde3158c1 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -82,7 +82,7 @@ class Microservice extends BaseCLIHandler { group: [constants.CMD_ADD, constants.CMD_UPDATE] }, { - name: 'microservice-id', alias: 'i', type: String, description: 'Microservice ID', + name: 'microservice-uuid', alias: 'i', type: String, description: 'Microservice UUID', group: [constants.CMD_UPDATE, constants.CMD_REMOVE, constants.CMD_INFO, constants.CMD_PORT_MAPPING_CREATE, constants.CMD_PORT_MAPPING_REMOVE, constants.CMD_PORT_MAPPING_LIST, constants.CMD_VOLUME_MAPPING_CREATE, constants.CMD_VOLUME_MAPPING_REMOVE, constants.CMD_VOLUME_MAPPING_LIST] @@ -100,7 +100,7 @@ class Microservice extends BaseCLIHandler { group: [constants.CMD_ADD] }, { - name: 'iofog-id', alias: 'I', type: String, description: 'ioFog node ID', + name: 'iofog-uuid', alias: 'I', type: String, description: 'ioFog node UUID', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { @@ -142,7 +142,7 @@ class Microservice extends BaseCLIHandler { group: [constants.CMD_ROUTE_CREATE, constants.CMD_ROUTE_REMOVE] }, { - name: 'internal-port', alias: 'b', type: String, description: 'Internal port', + name: 'internal-port', alias: 'b', type: Number, description: 'Internal port', group: [constants.CMD_PORT_MAPPING_REMOVE] }, { @@ -268,15 +268,15 @@ class Microservice extends BaseCLIHandler { example: '$ iofog-controller microservice add [other required options] --ports 80:8080:false 443:5443:false', }, { - desc: '4. Add routes (ABC:DEF - source microservice id : dest microservice id)', + desc: '4. Add routes (ABC:DEF - source microservice uuid : dest microservice uuid)', example: '$ iofog-controller microservice add [other required options] --routes ABC:DEF RFG:HJK' }, { - desc: '5. Add route (ABC:DEF - source microservice id : dest microservice id)', + desc: '5. Add route (ABC:DEF - source microservice uuid : dest microservice uuid)', example: '$ iofog-controller microservice route-create --route ABC:DEF', }, { - desc: '6. Delete route (ABC:DEF - source microservice id : dest microservice id)', + desc: '6. Delete route (ABC:DEF - source microservice uuid : dest microservice uuid)', example: '$ iofog-controller microservice route-remove --route ABC:DEF', }, { @@ -284,7 +284,7 @@ class Microservice extends BaseCLIHandler { example: '$ iofog-controller microservice port-mapping-create --mapping 80:8080:false -i ABC' }, { - desc: '8. Delete port mapping (80 - internal port, ABC - microservice id)', + desc: '8. Delete port mapping (80 - internal port, ABC - microservice uuid)', example: '$ iofog-controller microservice port-mapping-remove --internal-port 80 -i ABC' }, { @@ -317,63 +317,58 @@ async function _executeCase(commands, commandName, f, isUserRequired) { } const _createRoute = async function (obj, user) { - logger.info(JSON.stringify(obj)); try { const arr = obj.route.split(':'); - const sourceMicroserviceId = arr[0]; - const destMicroserviceId = arr[1]; - await MicroserviceService.createRoute(sourceMicroserviceId, destMicroserviceId, user, true); - logger.info(`Microservice route with source microservice ${sourceMicroserviceId} and dest microservice - ${destMicroserviceId} has been created successfully.`) + const sourceMicroserviceUuid = arr[0]; + const destMicroserviceUuid = arr[1]; + await MicroserviceService.createRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, true); + logger.info(`Microservice route with source microservice ${sourceMicroserviceUuid} and dest microservice + ${destMicroserviceUuid} has been created successfully.`) } catch (e) { logger.error(ErrorMessages.CLI.INVALID_ROUTE); } }; const _removeRoute = async function (obj, user) { - logger.info(JSON.stringify(obj)); try { const arr = obj.route.split(':'); - const sourceMicroserviceId = arr[0]; - const destMicroserviceId = arr[1]; - await MicroserviceService.deleteRoute(sourceMicroserviceId, destMicroserviceId, user, true); - logger.info(`Microservice route with source microservice ${obj.sourceMicroserviceId} and dest microservice - ${obj.destMicroserviceId} has been removed successfully.`); + const sourceMicroserviceUuid = arr[0]; + const destMicroserviceUuid = arr[1]; + await MicroserviceService.deleteRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, true); + logger.info('Microservice route with source microservice ' + sourceMicroserviceUuid + + ' and dest microservice ' + destMicroserviceUuid + 'has been removed successfully.'); } catch (e) { logger.error(ErrorMessages.CLI.INVALID_ROUTE); } }; const _createPortMapping = async function (obj, user) { - logger.info(JSON.stringify(obj)); const mapping = parsePortMappingObject(obj.mapping, ErrorMessages.CLI.INVALID_PORT_MAPPING); - await MicroserviceService.createPortMapping(obj.microserviceId, mapping, user, true); + await MicroserviceService.createPortMapping(obj.microserviceUuid, mapping, user, true); logger.info('Port mapping has been created successfully.'); }; const _createVolumeMapping = async function (obj, user) { - logger.info(JSON.stringify(obj)); const mapping = parseVolumeMappingObject(obj.mapping, ErrorMessages.CLI.INVALID_VOLUME_MAPPING); - const result = await MicroserviceService.createVolumeMapping(obj.microserviceId, mapping, user, true); - logger.info(JSON.stringify(result, null, 2)); - logger.info('Volume mapping has been created successfully.') + const result = await MicroserviceService.createVolumeMapping(obj.microserviceUuid, mapping, user, true); + logger.info(JSON.stringify({ + id: result.id + }, null, 2)); }; const _removePortMapping = async function (obj, user) { - logger.info(JSON.stringify(obj)); try { const internalPort = parseInt(obj.internalPort); - await MicroserviceService.deletePortMapping(obj.microserviceId, internalPort, user, true); - logger.info('Port mapping has been deleted successfully.'); + await MicroserviceService.deletePortMapping(obj.microserviceUuid, internalPort, user, true); + logger.info('Port mapping has been removed successfully.'); } catch (e) { logger.error(e.message); } }; const _removeVolumeMapping = async function (obj, user) { - logger.info(JSON.stringify(obj)); try { - await MicroserviceService.deleteVolumeMapping(obj.microserviceId, obj.mappingId, user, true); + await MicroserviceService.deleteVolumeMapping(obj.microserviceUuid, obj.mappingId, user, true); logger.info('Volume mapping has been deleted successfully.'); } catch (e) { logger.error(e.message); @@ -381,15 +376,13 @@ const _removeVolumeMapping = async function (obj, user) { }; const _listPortMappings = async function (obj, user) { - const result = await MicroserviceService.listMicroservicePortMappings(obj.microserviceId, user, true); + const result = await MicroserviceService.listMicroservicePortMappings(obj.microserviceUuid, user, true); logger.info(JSON.stringify(result, null, 2)); - logger.info('Port mappings have been retrieved successfully.'); }; const _listVolumeMappings = async function (obj, user) { - const result = await MicroserviceService.listVolumeMappings(obj.microserviceId, user, true); + const result = await MicroserviceService.listVolumeMappings(obj.microserviceUuid, user, true); logger.info(JSON.stringify(result, null, 2)); - logger.info('Volume mappings have been retrieved successfully.'); }; const _removeMicroservice = async function (obj, user) { @@ -397,21 +390,18 @@ const _removeMicroservice = async function (obj, user) { withCleanup: obj.cleanup }; - await MicroserviceService.deleteMicroservice(obj.microserviceId, microserviceData, user, true); + await MicroserviceService.deleteMicroservice(obj.microserviceUuid, microserviceData, user, true); logger.info('Microservice has been removed successfully.') }; const _listMicroservices = async function () { const result = await MicroserviceService.listMicroservices({}, {}, true); logger.info(JSON.stringify(result, null, 2)); - logger.info('Microservices have been retrieved successfully.'); }; const _getMicroservice = async function (obj, user) { - logger.info(JSON.stringify(obj)); - const result = await MicroserviceService.getMicroservice(obj.microserviceId, user, true); + const result = await MicroserviceService.getMicroservice(obj.microserviceUuid, user, true); logger.info(JSON.stringify(result, null, 2)); - logger.info('Microservice has been retrieved successfully.'); }; const _createMicroservice = async function (obj, user) { @@ -419,11 +409,10 @@ const _createMicroservice = async function (obj, user) { ? JSON.parse(fs.readFileSync(obj.file, 'utf8')) : _createMicroserviceObject(obj); - logger.info(JSON.stringify(microservice)); - const result = await MicroserviceService.createMicroservice(microservice, user, true); - logger.info(JSON.stringify(result)); - logger.info('Microservice has been created successfully.'); + logger.info(JSON.stringify({ + uuid: result.uuid + }, null, 2)) }; const _updateMicroservice = async function (obj, user) { @@ -431,9 +420,7 @@ const _updateMicroservice = async function (obj, user) { ? JSON.parse(fs.readFileSync(obj.file, 'utf8')) : _updateMicroserviceObject(obj); - logger.info(JSON.stringify(microservice)); - - await MicroserviceService.updateMicroservice(obj.microserviceId, microservice, user, true); + await MicroserviceService.updateMicroservice(obj.microserviceUuid, microservice, user, true); logger.info('Microservice has been updated successfully.'); }; @@ -441,7 +428,7 @@ const _updateMicroserviceObject = function (obj) { const microserviceObj = { name: obj.name, config: obj.config, - iofogUuid: obj.iofogId, + iofogUuid: obj.iofogUuid, rootHostAccess: AppHelper.validateBooleanCliOptions(obj.rootEnable, obj.rootDisable), logSize: obj.logSize, rebuild: obj.rebuild @@ -460,7 +447,7 @@ const _createMicroserviceObject = function (obj) { config: obj.config, catalogItemId: parseInt(obj.catalogId), flowId: parseInt(obj.flowId), - iofogUuid: obj.iofogId, + iofogUuid: obj.iofogUuid, rootHostAccess: AppHelper.validateBooleanCliOptions(obj.rootEnable, obj.rootDisable), logSize: obj.logSize, routes: obj.routes diff --git a/src/cli/registry.js b/src/cli/registry.js index 546feb879..4b91da34c 100644 --- a/src/cli/registry.js +++ b/src/cli/registry.js @@ -29,7 +29,7 @@ class Registry extends BaseCLIHandler { group: [constants.CMD] }, { - name: 'uri', alias: 'u', type: String, + name: 'uri', alias: 'U', type: String, description: 'Registry URI', group: [constants.CMD_ADD, constants.CMD_UPDATE] }, @@ -69,12 +69,12 @@ class Registry extends BaseCLIHandler { group: [constants.CMD_ADD, constants.CMD_UPDATE] }, { - name: 'user-id', alias: 'i', type: Number, + name: 'user-id', alias: 'u', type: Number, description: 'User\'s id', group: [constants.CMD_ADD] }, { - name: 'item-id', alias: 'd', type: Number, + name: 'item-id', alias: 'i', type: Number, description: 'Item\'s id', group: [constants.CMD_REMOVE, constants.CMD_UPDATE] } @@ -121,16 +121,15 @@ class Registry extends BaseCLIHandler { async function _createRegistry(obj, user) { const registry = _createRegistryObject(obj); - logger.info(JSON.stringify(registry)); const response = await RegistryService.createRegistry(registry, user); - logger.info('Registry has been created successfully.'); - logger.info('Registry id: ' + response.id); + logger.info(JSON.stringify({ + id: response.id + }, null, 2)); } async function _getRegistries(obj, user) { const result = await RegistryService.findRegistries(user, true); logger.info(JSON.stringify(result, null, 2)); - logger.info('List of Registries has been received successfully.'); } async function _deleteRegistry(obj, user) { @@ -140,7 +139,6 @@ async function _deleteRegistry(obj, user) { async function _updateRegistry(obj) { const registry = _createRegistryObject(obj); - logger.info(JSON.stringify(registry)); await RegistryService.updateRegistry(registry, obj.itemId, {}, true); logger.info('Registry has been updated successfully.'); } diff --git a/src/cli/tunnel.js b/src/cli/tunnel.js index 01759a1d3..304426321 100644 --- a/src/cli/tunnel.js +++ b/src/cli/tunnel.js @@ -59,8 +59,8 @@ class Tunnel extends BaseCLIHandler { group: [constants.CMD_UPDATE] }, { - name: 'iofogUuid', alias: 'f', type: String, - description: 'Fog UUID', + name: 'iofog-uuid', alias: 'i', type: String, + description: 'ioFog node UUID', group: [constants.CMD_UPDATE] }, { @@ -102,7 +102,10 @@ class Tunnel extends BaseCLIHandler { async function _updateTunnel(obj, user) { const action = obj.action; const tunnel = _createTunnelObject(obj); - logger.info(JSON.stringify(tunnel)); + if (tunnel.iofogUuid === undefined) { + throw new Error("Required field 'ioFog UUID' is missing."); + } + switch (action) { case 'open': await TunnelService.openTunnel(tunnel, user, true); @@ -119,7 +122,6 @@ async function _updateTunnel(obj, user) { async function _tunnelList() { const tunnels = await TunnelService.findAll(); logger.info(JSON.stringify(tunnels, null, 2)); - logger.info('Tunnels has been received successfully.'); } async function _executeCase(commands, commandName, f, isUserRequired) { diff --git a/src/cli/user.js b/src/cli/user.js index bf61143e3..ad885d416 100644 --- a/src/cli/user.js +++ b/src/cli/user.js @@ -130,10 +130,10 @@ const _createUser = async function (user) { user.password = AppHelper.encryptText(user.password, user.email); - logger.info(JSON.stringify(user)); - - await UserService.signUp(user, true); - logger.info('User created successfully.'); + const response = await UserService.signUp(user, true); + logger.info(JSON.stringify({ + id: response.userId + }), null, 2) }; const _updateUserDetails = async function (userDetails, user) { @@ -142,8 +142,6 @@ const _updateUserDetails = async function (userDetails, user) { }; const _deleteUser = async function (obj, user) { - logger.info(JSON.stringify(obj)); - await UserService.deleteUser(obj.force, user, true); logger.info('User removed successfully.'); }; @@ -151,19 +149,14 @@ const _deleteUser = async function (obj, user) { const _getAllUsers = async function () { const users = await UserService.list(true); logger.info(JSON.stringify(users, null, 2)); - logger.info('All users have been retrieved successfully.') }; const _generateToken = async function (emailObj, user) { - logger.info(JSON.stringify(emailObj)); - const response = await UserService.login(user, true); - logger.info('Access token ' + response.accessToken + ' created successfully.'); + logger.info(JSON.stringify(response, null, 2)); }; const _activateUser = async function (emailObj, user) { - logger.info(JSON.stringify(emailObj)); - const codeData = { userId: user.id }; @@ -173,8 +166,6 @@ const _activateUser = async function (emailObj, user) { }; const _suspendUser = async function (emailObj, user) { - logger.info(JSON.stringify(emailObj)); - await UserService.suspendUser(user, true); logger.info('User suspended successfully.'); }; diff --git a/src/config/default.json b/src/config/default.json index d10f5fa4b..f18f594eb 100644 --- a/src/config/default.json +++ b/src/config/default.json @@ -16,7 +16,9 @@ }, "Settings": { "UserTokenExpirationIntervalSeconds": 3600, - "FogTokenExpirationIntervalSeconds": 3600 + "FogTokenExpirationIntervalSeconds": 3600, + "FogStatusUpdateIntervalSeconds": 120, + "FogStatusFrequencySeconds": 60 }, "Diagnostics": { "DiagnosticDir": "diagnostic" diff --git a/src/config/development.json b/src/config/development.json index 5dffbac92..1a21cf099 100644 --- a/src/config/development.json +++ b/src/config/development.json @@ -16,7 +16,9 @@ }, "Settings": { "UserTokenExpirationIntervalSeconds": 360000, - "FogTokenExpirationIntervalSeconds": 3600000 + "FogTokenExpirationIntervalSeconds": 3600000, + "FogStatusUpdateIntervalSeconds": 120, + "FogStatusFrequencySeconds": 60 }, "Tunnel": { "Username": "username", diff --git a/src/config/production.json b/src/config/production.json index 6f7bc6ab8..ef1359bc3 100644 --- a/src/config/production.json +++ b/src/config/production.json @@ -11,6 +11,8 @@ }, "Settings": { "UserTokenExpirationIntervalSeconds": 3600, - "FogTokenExpirationIntervalSeconds": 3600 + "FogTokenExpirationIntervalSeconds": 3600, + "FogStatusUpdateIntervalSeconds": 120, + "FogStatusFrequencySeconds": 60 } } \ No newline at end of file diff --git a/src/controllers/agent-controller.js b/src/controllers/agent-controller.js index 6fc8c8330..e1740f6e3 100644 --- a/src/controllers/agent-controller.js +++ b/src/controllers/agent-controller.js @@ -19,11 +19,19 @@ const AuthDecorator = require('../decorators/authorization-decorator'); const agentProvisionEndPoint = async function (req) { const provisionData = req.body; - logger.info("Parameters:" + JSON.stringify(provisionData)); + logger.info("Parameters: " + JSON.stringify(provisionData)); return await AgentService.agentProvision(provisionData); }; +const agentDeprovisionEndPoint = async function (req, fog) { + const deprovisionData = req.body; + + logger.info("Parameters: " + JSON.stringify(deprovisionData)); + + return await AgentService.agentDeprovision(deprovisionData, fog); +}; + const getAgentConfigEndPoint = async function (req, fog) { return await AgentService.getAgentConfig(fog); }; @@ -31,7 +39,7 @@ const getAgentConfigEndPoint = async function (req, fog) { const updateAgentConfigEndPoint = async function (req, fog) { const updateData = req.body; - logger.info("Parameters:" + JSON.stringify(updateData)); + logger.info("Parameters: " + JSON.stringify(updateData)); return await AgentService.updateAgentConfig(updateData, fog); }; @@ -43,7 +51,7 @@ const getAgentConfigChangesEndPoint = async function (req, fog) { const updateAgentStatusEndPoint = async function (req, fog) { const agentStatus = req.body; - logger.info("Parameters:" + JSON.stringify(agentStatus)); + logger.info("Parameters: " + JSON.stringify(agentStatus)); return await AgentService.updateAgentStatus(agentStatus, fog); }; @@ -75,7 +83,7 @@ const getAgentStraceEndPoint = async function (req, fog) { const updateAgentStraceEndPoint = async function (req, fog) { const straceData = req.body; - logger.info("Parameters:" + JSON.stringify(straceData)); + logger.info("Parameters: " + JSON.stringify(straceData)); return await AgentService.updateAgentStrace(straceData, fog); }; @@ -87,7 +95,7 @@ const getAgentChangeVersionCommandEndPoint = async function (req, fog) { const updateHalHardwareInfoEndPoint = async function (req, fog) { const hardwareData = req.body; - logger.info("Parameters:" + JSON.stringify(hardwareData)); + logger.info("Parameters: " + JSON.stringify(hardwareData)); return await AgentService.updateHalHardwareInfo(hardwareData, fog); }; @@ -95,7 +103,7 @@ const updateHalHardwareInfoEndPoint = async function (req, fog) { const updateHalUsbInfoEndPoint = async function (req, fog) { const usbData = req.body; - logger.info("Parameters:" + JSON.stringify(usbData)); + logger.info("Parameters: " + JSON.stringify(usbData)); return await AgentService.updateHalUsbInfo(usbData, fog); }; @@ -114,6 +122,7 @@ const putImageSnapshotEndPoint = async function (req, fog) { module.exports = { agentProvisionEndPoint: agentProvisionEndPoint, + agentDeprovisionEndPoint: AuthDecorator.checkFogToken(agentDeprovisionEndPoint), getAgentConfigEndPoint: AuthDecorator.checkFogToken(getAgentConfigEndPoint), updateAgentConfigEndPoint: AuthDecorator.checkFogToken(updateAgentConfigEndPoint), getAgentConfigChangesEndPoint: AuthDecorator.checkFogToken(getAgentConfigChangesEndPoint), diff --git a/src/decorators/authorization-decorator.js b/src/decorators/authorization-decorator.js index 9702d2235..578456d54 100644 --- a/src/decorators/authorization-decorator.js +++ b/src/decorators/authorization-decorator.js @@ -29,8 +29,6 @@ function checkAuthToken(f) { const req = fArgs[0]; const token = req.headers.authorization; - logger.info('checking user token: ' + token); - const user = await UserManager.checkAuthentication(token); if (!user) { @@ -58,8 +56,6 @@ function checkFogToken(f) { const req = fArgs[0]; const token = req.headers.authorization; - logger.info('checking fog token: ' + token); - const fog = await FogManager.checkToken(token); if (!fog) { @@ -76,7 +72,6 @@ function checkFogToken(f) { FogAccessTokenManager.updateExpirationTime(fog.accessToken.id, fog.accessToken.expirationTime + config.get('Settings:FogTokenExpirationIntervalSeconds') * 1000); const timestamp = Date.now(); - logger.info('updating agent lastActive timestamp: ' + timestamp); await FogManager.updateLastActive(fog.uuid, timestamp); return await f.apply(this, fArgs); diff --git a/src/decorators/cli-decorator.js b/src/decorators/cli-decorator.js index c966d8761..5e5efb53e 100644 --- a/src/decorators/cli-decorator.js +++ b/src/decorators/cli-decorator.js @@ -50,8 +50,6 @@ function prepareUserByEmail(f) { const obj = fArgs[0] const email = obj.email - logger.info('getting user by email: ' + email) - const user = await UserManager.findByEmail(email) if (!user) { diff --git a/src/enums/fog-state.js b/src/enums/fog-state.js new file mode 100644 index 000000000..7c14e7a47 --- /dev/null +++ b/src/enums/fog-state.js @@ -0,0 +1,19 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2018 Edgeworx, Inc. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const fogState = { + UNKNOWN: 'UNKNOWN', + RUNNING: 'RUNNING' +}; + +module.exports = fogState; \ No newline at end of file diff --git a/src/enums/microservice-state.js b/src/enums/microservice-state.js index 4661b0171..1956f9109 100644 --- a/src/enums/microservice-state.js +++ b/src/enums/microservice-state.js @@ -1,9 +1,22 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2018 Edgeworx, Inc. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + const microserviceState = { NOT_RUNNING: 'NOT_RUNNING', RUNNING: 'RUNNING', RESTARTING: 'RESTARTING', STUCK_IN_RESTART: 'STUCK_IN_RESTART', -} +}; module.exports = microserviceState; diff --git a/src/helpers/app-helper.js b/src/helpers/app-helper.js index 6dacf9799..2cd8a0ad4 100644 --- a/src/helpers/app-helper.js +++ b/src/helpers/app-helper.js @@ -13,6 +13,7 @@ const crypto = require('crypto'); const Errors = require('./errors'); +const ErrorMessages = require('./error-messages'); const logger = require('../logger'); const fs = require('fs'); @@ -41,8 +42,8 @@ function decryptText(text, salt) { const processedSalt = crypto.createHash('md5').update(salt).digest("hex"); const textParts = text.split(':'); - const iv = new Buffer(textParts.shift(), 'hex'); - let encryptedText = new Buffer(textParts.join(':'), 'hex'); + const iv = Buffer.from(textParts.shift(), 'hex'); + let encryptedText = Buffer.from(textParts.join(':'), 'hex'); const decipher = crypto.createDecipheriv(ALGORITHM, processedSalt, iv); let dec = decipher.update(encryptedText, 'hex', 'utf8'); @@ -170,6 +171,12 @@ function handleCLIError(error) { case "InvalidArgumentError": console.log(error.message); break; + case "InvalidArgumentTypeError": + console.log(error.message); + break; + case "ALREADY_SET": + console.log("Parameter '" + error.optionName + "' is used multiple times"); + break; default: console.log(JSON.stringify(error)); break; @@ -189,6 +196,9 @@ function validateParameters(command, commandDefinitions, args) { const possibleAliasesList = _getPossibleAliasesList(command, commandDefinitions); const possibleArgsList = _getPossibleArgsList(command, commandDefinitions); + let currentArgType; + let currwentArgName; + for (const arg of args) { // arg is [argument, alias, value] @@ -196,13 +206,26 @@ function validateParameters(command, commandDefinitions, args) { // '--ssl-cert' format -> 'ssl-cert' format const argument = arg.substr(2); _validateArg(argument, possibleArgsList); + currwentArgName = argument; + currentArgType = _getValType(argument, commandDefinitions); } else if (arg.startsWith("-")) { // alias // '-q' format -> 'q' format const alias = arg.substr(1); _validateArg(alias, possibleAliasesList); + currwentArgName = alias; + currentArgType = _getValType(alias, commandDefinitions); } else { // value - continue; + let valType; + const nArg = new Number(arg); + if (isNaN(nArg)) { + valType = 'string'; + } else { + valType = 'number'; + } + if (valType !== currentArgType && currentArgType !== 'string') { + throw new Errors.InvalidArgumentTypeError(formatMessage(ErrorMessages.INVALID_CLI_ARGUMENT_TYPE, currwentArgName, currentArgType)) + } } } } @@ -261,6 +284,12 @@ function _getPossibleArgsList(command, commandDefinitions) { return possibleArgsList; } +function _getValType(arg, commandDefinitions) { + const command = commandDefinitions + .filter(def => def.name === arg || def.alias === arg)[0]; + return command.type.name.toLowerCase(); +} + function isTest() { return process.env.NODE_ENV === 'test' } diff --git a/src/helpers/error-messages.js b/src/helpers/error-messages.js index 37e68e8d7..7544a4145 100644 --- a/src/helpers/error-messages.js +++ b/src/helpers/error-messages.js @@ -12,15 +12,16 @@ */ module.exports = { - DUPLICATE_NAME: 'Duplicate name {}', + INVALID_CLI_ARGUMENT_TYPE: 'Type of argument "{}" should be a {}', + DUPLICATE_NAME: "Duplicate name '{}'", ALREADY_EXISTS: 'Model already exists', - INVALID_CATALOG_ITEM_ID: 'Invalid catalog item id {}', - INVALID_FLOW_ID: 'Invalid flow id {}', - INVALID_REGISTRY_ID: 'Invalid registry id {}', - INVALID_CONNECTOR_IP: 'Invalid connector IP {}', + INVALID_CATALOG_ITEM_ID: "Invalid catalog item id '{}'", + INVALID_FLOW_ID: "Invalid flow id '{}'", + INVALID_REGISTRY_ID: "Invalid registry id '{}'", + INVALID_CONNECTOR_IP: "Invalid connector IP '{}'", UNABLE_TO_CREATE_ACTIVATION_CODE: 'Unable to create activation code', UNABLE_TO_GET_ACTIVATION_CODE: 'Unable to create activation code', - INVALID_FOG_NODE_UUID: 'Invalid ioFog UUID {}', + INVALID_IOFOG_UUID: "Invalid ioFog UUID '{}'", INVALID_USER_EMAIL: 'Invalid user email', INVALID_MICROSERVICE_UUID: "Invalid microservice UUID '{}'", INVALID_MICROSERVICE_STRACE: "Strace data for this microservice not found", @@ -32,15 +33,14 @@ module.exports = { USER_NOT_UPDATED: 'User not updated', EMAIL_NOT_ACTIVATED: 'Email is not activated. Please activate your account first.', REGISTRATION_FAILED: 'Registration failed: There is already an account associated with your email address. Please try logging in instead.', - INVALID_NODE_ID: 'Invalid ioFog UUID', INVALID_PROVISIONING_KEY: 'Invalid Provisioning Key', EMAIL_SENDER_NOT_CONFIGURED: 'Email sender not configured', INVALID_PORT_FORMAT: 'Invalid port format', INVALID_FILE_PATH: 'Invalid file path', - PORT_NOT_AVAILABLE: 'Port {} is not available', - UNABLE_TO_WRITE_STRACE: 'Error while writing strace data to file. File name: {}, err: {}', - UNABLE_TO_DELETE_STRACE: 'Error while deleting strace data file. File name: {}, err: {}', - FTP_ERROR: 'FTP error: {}', + PORT_NOT_AVAILABLE: "Port '{}' is not available", + UNABLE_TO_WRITE_STRACE: "Error while writing strace data to file. File name: '{}', err: '{}'", + UNABLE_TO_DELETE_STRACE: "Error while deleting strace data file. File name: '{}', err: '{}'", + FTP_ERROR: "FTP error: '{}'", EXPIRED_PROVISION_KEY: 'Expired provision key', VERSION_COMMAND_NOT_FOUND: 'Version command not found', STRACE_WITHOUT_FOG: "Can't run strace for microservice without ioFog.", @@ -74,5 +74,10 @@ module.exports = { }, CONNECTOR_IS_IN_USE: 'You can\'t delete connector, because it is used for routing now.', INVALID_VERSION_COMMAND_UPGRADE: 'Can\'t upgrade version now. Latest is already installed', - INVALID_VERSION_COMMAND_ROLLBACK: 'Can\'t rollback version now. There are no backups on agent' + INVALID_VERSION_COMMAND_ROLLBACK: 'Can\'t rollback version now. There are no backups on agent', + CATALOG_ITEM_IMAGES_IS_FROZEN: 'Can\'t update catalog item images for item used for running microservices', + SYSTEM_CATALOG_ITEM_UPDATE: 'Catalog item id {} is systemic and can\'t be updated', + SYSTEM_CATALOG_ITEM_DELETE: 'Catalog item id {} is systemic and can\'t be deleted', + CATALOG_UPDATE_NO_FIELDS: 'Add some parameters which should be updated.', + CATALOG_UPDATE_REQUIRES_ID: "Parameter '--item-id' is missing, update requires Catalog id." }; diff --git a/src/helpers/errors.js b/src/helpers/errors.js index 08b16e1bd..1fc6b7cac 100644 --- a/src/helpers/errors.js +++ b/src/helpers/errors.js @@ -95,6 +95,14 @@ class InvalidArgumentError extends Error { } } +class InvalidArgumentTypeError extends Error { + constructor(message) { + super(message); + this.message = message; + this.name = "InvalidArgumentTypeError"; + } +} + module.exports = { AuthenticationError: AuthenticationError, TransactionError: TransactionError, @@ -105,5 +113,7 @@ module.exports = { DuplicatePropertyError: DuplicatePropertyError, FtpError: FtpError, EmailActivationSetupError: EmailActivationSetupError, - InvalidArgumentError: InvalidArgumentError + InvalidArgumentError: InvalidArgumentError, + InvalidArgumentTypeError: InvalidArgumentTypeError + }; \ No newline at end of file diff --git a/src/jobs/base/base-job-handler.js b/src/jobs/base/base-job-handler.js new file mode 100644 index 000000000..0f356cbfa --- /dev/null +++ b/src/jobs/base/base-job-handler.js @@ -0,0 +1,26 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2018 Edgeworx, Inc. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const Config = require('../../config'); + +class BaseJobHandler { + constructor() { + this.scheduleTime = Config.get('Settings:FogStatusUpdateIntervalSeconds') * 1000; + } + + run() { + throw new Error('Not Implemented'); + } +} + +module.exports = BaseJobHandler; \ No newline at end of file diff --git a/src/jobs/fog-status-job.js b/src/jobs/fog-status-job.js new file mode 100644 index 000000000..78aa256cb --- /dev/null +++ b/src/jobs/fog-status-job.js @@ -0,0 +1,72 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2018 Edgeworx, Inc. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const TransactionDecorator = require('../decorators/transaction-decorator'); + +const FogManager = require('../sequelize/managers/iofog-manager'); +const MicroserviceManager = require('../sequelize/managers/microservice-manager'); +const MicroserviceStatusManager = require('../sequelize/managers/microservice-status-manager'); +const MicroserviceService = require('../services/microservices-service'); +const MicroserviceStates = require('../enums/microservice-state'); +const FogStates = require('../enums/fog-state'); +const BaseJobHandler = require('./base/base-job-handler'); +const Config = require('../config'); + +class FogStatusJob extends BaseJobHandler { + constructor() { + super() + } + + run() { + setInterval(TransactionDecorator.generateFakeTransaction(updateFogsConnectionStatus), this.scheduleTime); + } +} + +async function updateFogsConnectionStatus(transaction) { + const unknownFogUuids = await _updateFogStatus(transaction); + const microservices = await _updateMicroserviceStatus(unknownFogUuids, transaction); + await _deleteNotRunningMicroservices(microservices, transaction); +} + +async function _updateFogStatus(transaction) { + const minInMs = Config.get('Settings:FogStatusFrequencySeconds') * 1000; + const fogs = await FogManager.findAll({daemonStatus: FogStates.RUNNING}, transaction); + const unknownFogUuids = fogs + .filter(fog => { + const intervalInMs = fog.statusFrequency > minInMs ? fog.statusFrequency * 2 : minInMs; + return Date.now() - fog.lastStatusTime > intervalInMs + }) + .map(fog => fog.uuid); + + const where = {uuid: unknownFogUuids}; + const data = {daemonStatus: FogStates.UNKNOWN, ipAddress: '0.0.0.0'}; + await FogManager.update(where, data, transaction); + return unknownFogUuids; +} + +async function _updateMicroserviceStatus(unknownFogUuids, transaction) { + const microservices = await MicroserviceManager.findAllWithStatuses({iofogUuid: unknownFogUuids}, transaction); + const microserviceStatusIds = microservices.map(microservice => microservice.microserviceStatus.id); + await MicroserviceStatusManager.update({id: microserviceStatusIds}, {status: MicroserviceStates.NOT_RUNNING}, transaction); + return microservices; +} + +async function _deleteNotRunningMicroservices(microservices, transaction) { + for (microservice of microservices) { + if (microservice.delete) { + await MicroserviceService.deleteMicroserviceWithRoutesAndPortMappings(microservice.uuid, transaction) + } + } +} + +module.exports = new FogStatusJob(); \ No newline at end of file diff --git a/src/routes/agent.js b/src/routes/agent.js index 2ab7f255d..b5d4daacf 100644 --- a/src/routes/agent.js +++ b/src/routes/agent.js @@ -46,16 +46,36 @@ module.exports = [ .send(responseObject.body) } }, + { + method: 'post', + path: '/api/v3/agent/deprovision', + middleware: async (req, res) => { + const successCode = constants.HTTP_CODE_NO_CONTENT; + const errorCodes = [ + { + code: constants.HTTP_CODE_UNAUTHORIZED, + errors: [Errors.AuthenticationError] + }, + { + code: constants.HTTP_CODE_BAD_REQUEST, + errors: [Errors.ValidationError] + } + ]; + + const agentDeprovisionEndPoint = ResponseDecorator.handleErrors(AgentController.agentDeprovisionEndPoint, successCode, errorCodes); + const responseObject = await agentDeprovisionEndPoint(req); + + res + .status(responseObject.code) + .send(responseObject.body) + } + }, { method: 'get', path: '/api/v3/agent/config', middleware: async (req, res) => { const successCode = constants.HTTP_CODE_SUCCESS; const errorCodes = [ - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - }, { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] @@ -76,10 +96,6 @@ module.exports = [ middleware: async (req, res) => { const successCode = constants.HTTP_CODE_NO_CONTENT; const errorCodes = [ - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - }, { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] @@ -104,10 +120,6 @@ module.exports = [ middleware: async (req, res) => { const successCode = constants.HTTP_CODE_SUCCESS; const errorCodes = [ - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - }, { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] @@ -132,10 +144,6 @@ module.exports = [ middleware: async (req, res) => { const successCode = constants.HTTP_CODE_NO_CONTENT; const errorCodes = [ - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - }, { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] @@ -160,10 +168,6 @@ module.exports = [ middleware: async (req, res) => { const successCode = constants.HTTP_CODE_SUCCESS; const errorCodes = [ - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - }, { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] @@ -208,10 +212,6 @@ module.exports = [ middleware: async (req, res) => { const successCode = constants.HTTP_CODE_SUCCESS; const errorCodes = [ - { - code: constants.HTTP_CODE_NOT_FOUND, - errors: [Errors.NotFoundError] - }, { code: constants.HTTP_CODE_UNAUTHORIZED, errors: [Errors.AuthenticationError] diff --git a/src/schemas/agent.js b/src/schemas/agent.js index e1bfbb44a..e6cc0e3e9 100644 --- a/src/schemas/agent.js +++ b/src/schemas/agent.js @@ -22,6 +22,19 @@ const agentProvision = { "additionalProperties": false }; +const agentDeprovision = { + "id": "/agentDeprovision", + "type": "object", + "properties": { + "microserviceUuids": { + "type": "array", + "items": {"type": "string"} + } + }, + "required": ["microserviceUuids"], + "additionalProperties": false +}; + const updateAgentConfig = { "id": "/updateAgentConfig", "type": "object", @@ -139,7 +152,7 @@ const updateUsbInfo = { }; module.exports = { - mainSchemas: [agentProvision, updateAgentConfig, updateAgentStatus, updateAgentStrace, + mainSchemas: [agentProvision, agentDeprovision, updateAgentConfig, updateAgentStatus, updateAgentStrace, updateHardwareInfo, updateUsbInfo], innerSchemas: [straceData, microserviceStatus] }; \ No newline at end of file diff --git a/src/schemas/index.js b/src/schemas/index.js index 7f524724b..492e09d1d 100644 --- a/src/schemas/index.js +++ b/src/schemas/index.js @@ -77,6 +77,9 @@ async function handleValidationError(error) { case "enum": message = "Field " + error.stack.replace('instance.', ''); break; + case "minimum": + message = error.stack.replace('instance.', ''); + break; default: message = JSON.stringify(error); break; diff --git a/src/schemas/microservice.js b/src/schemas/microservice.js index 70d44bfa1..bc80103ef 100644 --- a/src/schemas/microservice.js +++ b/src/schemas/microservice.js @@ -7,7 +7,10 @@ const microserviceCreate = { "minLength": 1 }, "config": {"type": "string"}, - "catalogItemId": {"type": "integer"}, + "catalogItemId": { + "type": "integer", + "minimum": 4 + }, "flowId": {"type": "integer"}, "iofogUuid": {"type": "string"}, "rootHostAccess": {"type": "boolean"}, diff --git a/src/sequelize/managers/microservice-manager.js b/src/sequelize/managers/microservice-manager.js index ca103f664..00d73f571 100644 --- a/src/sequelize/managers/microservice-manager.js +++ b/src/sequelize/managers/microservice-manager.js @@ -233,7 +233,7 @@ class MicroserviceManager extends BaseManager { }, {transaction: transaction}) } - findAllWithStatuses(transaction) { + findAllWithStatuses(where, transaction) { return Microservice.findAll({ include: [ { @@ -241,7 +241,8 @@ class MicroserviceManager extends BaseManager { as: 'microserviceStatus', required: true } - ] + ], + where: where }, {transaction: transaction}) } diff --git a/src/sequelize/managers/strace-manager.js b/src/sequelize/managers/strace-manager.js index 8d0f50422..c35cfe21e 100644 --- a/src/sequelize/managers/strace-manager.js +++ b/src/sequelize/managers/strace-manager.js @@ -17,6 +17,7 @@ const Strace = models.StraceDiagnostics; const Errors = require('../../helpers/errors'); const ErrorMessages = require('../../helpers/error-messages'); +const AppHelper = require('../../helpers/app-helper'); const maxBufferSize = 1e8; @@ -31,7 +32,7 @@ class StraceManager extends BaseManager { microserviceUuid: uuid }, transaction); if (!strace) { - throw new Errors.NotFoundError(ErrorMessages.INVALID_NODE_ID) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, uuid)); } let newBuffer = this._updateBuffer(strace.buffer, pushingData); diff --git a/src/sequelize/managers/user-manager.js b/src/sequelize/managers/user-manager.js index 4d4469dba..ccde91ed3 100644 --- a/src/sequelize/managers/user-manager.js +++ b/src/sequelize/managers/user-manager.js @@ -16,10 +16,6 @@ const models = require('./../models'); const User = models.User; const AccessToken = models.AccessToken; const AppHelper = require('../../helpers/app-helper'); -const Flow = models.Flow; -const Fog = models.Fog; -const CatalogItem = models.CatalogItem; -const Microservice = models.Microservice; class UserManager extends BaseManager { getEntity() { diff --git a/src/sequelize/managers/volume-mapping-manager.js b/src/sequelize/managers/volume-mapping-manager.js index 28f515e97..e0810b8f6 100644 --- a/src/sequelize/managers/volume-mapping-manager.js +++ b/src/sequelize/managers/volume-mapping-manager.js @@ -14,7 +14,6 @@ const BaseManager = require('./base-manager'); const models = require('./../models'); const VolumeMapping = models.VolumeMapping; -const Microservice = models.Microservice; class VolumeMappingManager extends BaseManager { getEntity() { diff --git a/src/server.js b/src/server.js index fc39b4d78..50b4ab214 100644 --- a/src/server.js +++ b/src/server.js @@ -24,8 +24,19 @@ const path = require('path'); const {renderFile} = require('ejs'); const xss = require('xss-clean'); const morgan = require('morgan'); +const fogStatusJob = require('./jobs/fog-status-job'); +const packageJson = require('../package'); const app = express(); +const Sentry = require('@sentry/node'); + +Sentry.init({ dsn: 'https://a15f11352d404c2aa4c8f321ad9e759a@sentry.io/1378602' }); +Sentry.configureScope(scope => { + scope.setExtra('version', packageJson.version); +}); + +app.use(Sentry.Handlers.requestHandler()); +app.use(Sentry.Handlers.errorHandler()); app.use(helmet()); app.use(xss()); @@ -66,22 +77,35 @@ const setupMiddleware = function (routeName) { fs.readdirSync(path.join(__dirname, 'routes')) .forEach(setupMiddleware); -function startHttpServer(app, port) { - logger.silly("| SSL not configured, starting HTTP server.|") +let jobs = []; + +const setupJobs = function (file) { + jobs.push((require(path.join(__dirname, 'jobs', file)) || [])); +}; + +fs.readdirSync(path.join(__dirname, 'jobs')) + .filter(file => { + return (file.indexOf('.') !== 0) && (file.slice(-3) === '.js'); + }) + .forEach(setupJobs); + +function startHttpServer(app, port, jobs) { + logger.silly("| SSL not configured, starting HTTP server.|"); - logger.silly("------------------------------------------") - logger.silly("| SSL not configured, starting HTTP server.|") - logger.silly("------------------------------------------") + logger.silly("------------------------------------------"); + logger.silly("| SSL not configured, starting HTTP server.|"); + logger.silly("------------------------------------------"); app.listen(port, function onStart(err) { if (err) { logger.error(err) } - logger.silly(`==> 🌎 Listening on port ${port}. Open up http://localhost:${port}/ in your browser.`, port, port) + logger.silly(`==> 🌎 Listening on port ${port}. Open up http://localhost:${port}/ in your browser.`, port, port); + jobs.forEach(job => job.run()); }) } -function startHttpsServer(app, port, sslKey, sslCert, intermedKey) { +function startHttpsServer(app, port, sslKey, sslCert, intermedKey, jobs) { try { let sslOptions = { key: fs.readFileSync(sslKey), @@ -95,7 +119,8 @@ function startHttpsServer(app, port, sslKey, sslCert, intermedKey) { if (err) { logger.error(err) } - logger.silly(`==> 🌎 HTTPS server listening on port ${port}. Open up https://localhost:${port}/ in your browser.`) + logger.silly(`==> 🌎 HTTPS server listening on port ${port}. Open up https://localhost:${port}/ in your browser.`); + jobs.forEach(job => job.run()); }) } catch (e) { logger.error('ssl_key or ssl_cert or intermediate_cert is either missing or invalid. Provide valid SSL configurations.') @@ -107,10 +132,10 @@ const port = config.get('Server:Port'), sslKey = config.get('Server:SslKey'), sslCert = config.get('Server:SslCert'), - intermedKey = config.get('Server:IntermediateCert') + intermedKey = config.get('Server:IntermediateCert'); if (!devMode && sslKey && sslCert && intermedKey) { - startHttpsServer(app, port, sslKey, sslCert, intermedKey) + startHttpsServer(app, port, sslKey, sslCert, intermedKey, jobs) } else { - startHttpServer(app, port) + startHttpServer(app, port, jobs) } diff --git a/src/services/agent-service.js b/src/services/agent-service.js index e1c24ccc3..d81e6a676 100644 --- a/src/services/agent-service.js +++ b/src/services/agent-service.js @@ -21,6 +21,8 @@ const FogVersionCommandManager = require('../sequelize/managers/iofog-version-co const StraceManager = require('../sequelize/managers/strace-manager'); const RegistryManager = require('../sequelize/managers/registry-manager'); const MicroserviceStatusManager = require('../sequelize/managers/microservice-status-manager') +const MicroserviceStates = require('../enums/microservice-state'); +const FogStates = require('../enums/fog-state'); const Validator = require('../schemas'); const Errors = require('../helpers/errors'); const AppHelper = require('../helpers/app-helper'); @@ -39,7 +41,6 @@ const Op = Sequelize.Op; const IncomingForm = formidable.IncomingForm; const agentProvision = async function (provisionData, transaction) { - await Validator.validate(provisionData, Validator.schemas.agentProvision); const provision = await FogProvisionKeyManager.findOne({ @@ -81,6 +82,28 @@ const agentProvision = async function (provisionData, transaction) { }; +const agentDeprovision = async function (deprovisionData, fog, transaction) { + await Validator.validate(deprovisionData, Validator.schemas.agentDeprovision); + + await MicroserviceStatusManager.update( + {microserviceUuid: deprovisionData.microserviceUuids}, + {status: MicroserviceStates.NOT_RUNNING}, + transaction + ); + + await _invalidateFogNode(fog, transaction); +}; + +const _invalidateFogNode = async function (fog, transaction) { + const where = {uuid: fog.uuid}; + const data = {daemonStatus: FogStates.UNKNOWN, ipAddress: '0.0.0.0'}; + await FogManager.update(where, data, transaction); + const updatedFog = Object.assign({}, fog); + updatedFog.daemonStatus = FogStates.UNKNOWN; + updatedFog.ipAddress = '0.0.0.0'; + return updatedFog; +}; + const getAgentConfig = async function (fog) { return { networkInterface: fog.networkInterface, @@ -129,14 +152,14 @@ const updateAgentConfig = async function (updateData, fog, transaction) { }, update, transaction); }; -const getAgentConfigChanges = async function (fog, transaction) { +const getAgentConfigChanges = async function (ioFog, transaction) { - const changeTracking = await ChangeTrackingService.getByIoFogUuid(fog.uuid, transaction); + const changeTracking = await ChangeTrackingService.getByIoFogUuid(ioFog.uuid, transaction); if (!changeTracking) { - throw new Errors.NotFoundError(ErrorMessages.INVALID_NODE_ID) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID), ioFog.uuid); } - await ChangeTrackingService.updateIfChanged(fog.uuid, ChangeTrackingService.events.clean, transaction); + await ChangeTrackingService.updateIfChanged(ioFog.uuid, ChangeTrackingService.events.clean, transaction); return { config: changeTracking.config, @@ -188,7 +211,7 @@ const updateAgentStatus = async function (agentStatus, fog, transaction) { }, fogStatus, transaction); await _updateMicroserviceStatuses(JSON.parse(agentStatus.microserviceStatus), transaction); - await MicroserviceService.deleteNotRunningMicroservices(transaction); + await MicroserviceService.deleteNotRunningMicroservices(fog, transaction); }; @@ -329,7 +352,6 @@ const updateAgentStrace = async function (straceData, fog, transaction) { const buffer = strace.buffer; await StraceManager.pushBufferByMicroserviceUuid(microserviceUuid, buffer, transaction) } - }; const getAgentChangeVersionCommand = async function (fog, transaction) { @@ -471,6 +493,7 @@ async function _checkMicroservicesFogType(fog, fogTypeId, transaction) { module.exports = { agentProvision: TransactionDecorator.generateFakeTransaction(agentProvision), + agentDeprovision: TransactionDecorator.generateFakeTransaction(agentDeprovision), getAgentConfig: getAgentConfig, updateAgentConfig: TransactionDecorator.generateFakeTransaction(updateAgentConfig), getAgentConfigChanges: TransactionDecorator.generateFakeTransaction(getAgentConfigChanges), diff --git a/src/services/catalog-service.js b/src/services/catalog-service.js index 18274a980..8f7c57dd2 100644 --- a/src/services/catalog-service.js +++ b/src/services/catalog-service.js @@ -22,6 +22,9 @@ const CatalogItemOutputTypeManager = require('../sequelize/managers/catalog-item const Op = require('sequelize').Op; const Validator = require('../schemas/index'); const RegistryManager = require('../sequelize/managers/registry-manager'); +const MicroserviceManager = require('../sequelize/managers/microservice-manager'); +const ChangeTrackingService = require('./change-tracking-service'); +const MicroseriveStates = require('../enums/microservice-state'); const createCatalogItem = async function (data, user, transaction) { await Validator.validate(data, Validator.schemas.catalogItemCreate); @@ -41,8 +44,13 @@ const updateCatalogItem = async function (id, data, user, isCLI, transaction) { await Validator.validate(data, Validator.schemas.catalogItemUpdate); const where = isCLI - ? {id: id} - : {id: id, userId: user.id}; + ? { + id: id + } + : { + id: id, + userId: user.id + }; data.id = id; await _updateCatalogItem(data, where, transaction); @@ -52,8 +60,11 @@ const updateCatalogItem = async function (id, data, user, isCLI, transaction) { const listCatalogItems = async function (user, isCLI, transaction) { const where = isCLI - ? {category: {[Op.ne]: 'SYSTEM'}} - : {[Op.or]: [{userId: user.id}, {userId: null}], category: {[Op.ne]: 'SYSTEM'}}; + ? {} + : { + [Op.or]: [{userId: user.id}, {userId: null}], + [Op.or]: [{category: {[Op.ne]: 'SYSTEM'}}, {category: null}] + }; const attributes = isCLI ? {} @@ -67,8 +78,12 @@ const listCatalogItems = async function (user, isCLI, transaction) { const getCatalogItem = async function (id, user, isCLI, transaction) { const where = isCLI - ? {id: id, category: {[Op.ne]: 'SYSTEM'}} - : {[Op.or]: [{userId: user.id}, {userId: null}], id: id, category: {[Op.ne]: 'SYSTEM'}}; + ? {id: id} + : { + id: id, + [Op.or]: [{userId: user.id}, {userId: null}], + [Op.or]: [{category: {[Op.ne]: 'SYSTEM'}}, {category: null}] + }; const attributes = isCLI ? {} @@ -82,9 +97,22 @@ const getCatalogItem = async function (id, user, isCLI, transaction) { }; const deleteCatalogItem = async function (id, user, isCLI, transaction) { + const where = isCLI - ? {id: id} - : {userId: user.id, id: id}; + ? { + id: id + } + : { + userId: user.id, + id: id + }; + + const item = await _checkIfItemExists(where, transaction); + + if (item.category == "SYSTEM"){ + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.SYSTEM_CATALOG_ITEM_DELETE, id)); + } + const affectedRows = await CatalogItemManager.delete(where, transaction); if (affectedRows === 0) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_CATALOG_ITEM_ID, id)); @@ -168,6 +196,13 @@ const _createCatalogItem = async function (data, user, transaction) { catalogItem = AppHelper.deleteUndefinedFields(catalogItem); + if (catalogItem.registryId) { + const registry = await RegistryManager.findOne({id: catalogItem.registryId}, transaction); + if (!registry) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_REGISTRY_ID, data.registryId)); + } + } + return await CatalogItemManager.create(catalogItem, transaction); }; @@ -245,20 +280,34 @@ const _updateCatalogItem = async function (data, where, transaction) { catalogItem = AppHelper.deleteUndefinedFields(catalogItem); if (!catalogItem || AppHelper.isEmpty(catalogItem)) { - return + throw new Errors.NotFoundError(ErrorMessages.CATALOG_UPDATE_NO_FIELDS); } - const registry = await RegistryManager.findOne({id: data.registryId}, transaction); - if (!registry) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_REGISTRY_ID, data.registryId)); + if (data.registryId) { + const registry = await RegistryManager.findOne({id: data.registryId}, transaction); + if (!registry) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_REGISTRY_ID, data.registryId)); + } } const item = await _checkIfItemExists(where, transaction); + + if (item.category === "SYSTEM"){ + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.SYSTEM_CATALOG_ITEM_UPDATE, data.id)); + } + await _checkForDuplicateName(data.name, item, transaction); await CatalogItemManager.update(where, catalogItem, transaction); }; const _updateCatalogItemImages = async function (data, transaction) { if (data.images) { + const microservices = await MicroserviceManager.findAllWithStatuses({catalogItemId: data.id}, transaction); + for (const ms of microservices) { + if (ms.microserviceStatus.status === MicroseriveStates.RUNNING) { + throw new Errors.ValidationError(ErrorMessages.CATALOG_ITEM_IMAGES_IS_FROZEN) + } + } + for (const image of data.images) { await CatalogItemImageManager.updateOrCreate({ catalogItemId: data.id, diff --git a/src/services/connector-service.js b/src/services/connector-service.js index c902fc3f8..1cb79b252 100644 --- a/src/services/connector-service.js +++ b/src/services/connector-service.js @@ -50,10 +50,18 @@ async function updateConnector(connectorData, transaction) { const queryConnectorData = { publicIp: connectorData.publicIp }; + + const connector = await ConnectorManager.findOne({ + publicIp: connectorData.publicIp + }, transaction); + if (!connector) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_CONNECTOR_IP, connectorData.publicIp)) + } + await ConnectorManager.update(queryConnectorData, connectorData, transaction); - const connector = await ConnectorManager.findOne({publicIp: connectorData.publicIp}, transaction); - await MicroserviceService.updateRouteOverConnector(connector, transaction); - await MicroserviceService.updatePortMappingOverConnector(connector, transaction); + const updatedConnector = await ConnectorManager.findOne({publicIp: connectorData.publicIp}, transaction); + await MicroserviceService.updateRouteOverConnector(updatedConnector, transaction); + await MicroserviceService.updatePortMappingOverConnector(updatedConnector, transaction); } async function deleteConnector(connectorData, transaction) { diff --git a/src/services/diagnostic-service.js b/src/services/diagnostic-service.js index 2f3349eeb..368125344 100644 --- a/src/services/diagnostic-service.js +++ b/src/services/diagnostic-service.js @@ -23,7 +23,7 @@ const MicroserviceManager = require('../sequelize/managers/microservice-manager' const Config = require('../config'); const fs = require('fs'); const logger = require('../logger'); -const ftpClient = require('ftp'); +const FtpClient = require('ftp'); const mime = require('mime'); @@ -189,7 +189,7 @@ const _sendFileToFtp = async function (data, filePath) { const writeFileToFtp = function (connectionData, filePath, destDir) { return new Promise((resolve, reject) => { - const client = new ftpClient(); + const client = new FtpClient(); client.on('ready', () => { client.put(filePath, destDir + '/' + filePath.split('/').pop(), err => { @@ -235,7 +235,7 @@ const _convertFileToBase64 = function (filePath) { }; const _deleteFile = function (filePath) { - fs.unlinkSync(filePath, (err) => { + fs.unlink(filePath, (err) => { if (err) { logger.warn(AppHelper.formatMessage(ErrorMessages.UNABLE_TO_DELETE_STRACE, filePath, err)); } diff --git a/src/services/flow-service.js b/src/services/flow-service.js index 3ef591730..4528ac800 100644 --- a/src/services/flow-service.js +++ b/src/services/flow-service.js @@ -119,7 +119,7 @@ const getFlow = async function (flowId, user, isCLI, transaction) { const _checkForDuplicateName = async function (name, flowId, userId, transaction) { if (name) { const where = flowId - ? {name: name, id: {[Op.ne]: flowId, userId: userId}} + ? {name: name, userId: userId, id: {[Op.ne]: flowId}} : {name: name, userId: userId}; const result = await FlowManager.findOne(where, transaction); diff --git a/src/services/iofog-service.js b/src/services/iofog-service.js index ef5002a4e..62233c1a7 100644 --- a/src/services/iofog-service.js +++ b/src/services/iofog-service.js @@ -24,6 +24,7 @@ const HWInfoManager = require('../sequelize/managers/hw-info-manager'); const USBInfoManager = require('../sequelize/managers/usb-info-manager'); const CatalogService = require('../services/catalog-service'); const MicroserviceManager = require('../sequelize/managers/microservice-manager'); +const FogStates = require('../enums/fog-state'); async function createFog(fogData, user, isCLI, transaction) { await Validator.validate(fogData, Validator.schemas.iofogCreate); @@ -110,7 +111,7 @@ async function updateFog(fogData, user, isCLI, transaction) { const oldFog = await FogManager.findOne(queryFogData, transaction); if (!oldFog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, fogData.uuid)) } await FogManager.update(queryFogData, updateFogData, transaction); @@ -150,9 +151,8 @@ async function deleteFog(fogData, user, isCLI, transaction) { const fog = await FogManager.findOne(queryFogData, transaction); if (!fog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, fogData.uuid)) } - await _updateFogsConnectionStatus(fog, transaction); await _processDeleteCommand(fog, transaction) } @@ -165,60 +165,58 @@ async function getFog(fogData, user, isCLI, transaction) { const fog = await FogManager.findOne(queryFogData, transaction); if (!fog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, fogData.uuid)) } - const updatedFog = await _updateFogsConnectionStatus(fog, transaction); - return { - uuid: updatedFog.uuid, - name: updatedFog.name, - location: updatedFog.location, - gpsMode: updatedFog.gpsMode, - latitude: updatedFog.latitude, - longitude: updatedFog.longitude, - description: updatedFog.description, - lastActive: updatedFog.lastActive, - daemonStatus: updatedFog.daemonStatus, - daemonOperatingDuration: updatedFog.daemonOperatingDuration, - daemonLastStart: updatedFog.daemonLastStart, - memoryUsage: updatedFog.memoryUsage, - diskUsage: updatedFog.diskUsage, - cpuUsage: updatedFog.cpuUsage, - memoryViolation: updatedFog.memoryViolation, - diskViolation: updatedFog.diskViolation, - cpuViolation: updatedFog.cpuViolation, - catalogItemStatus: updatedFog.catalogItemStatus, - repositoryCount: updatedFog.repositoryCount, - repositoryStatus: updatedFog.repositoryStatus, - systemTime: updatedFog.systemTime, - lastStatusTime: updatedFog.lastStatusTime, - ipAddress: updatedFog.ipAddress, - processedMessages: updatedFog.processedMessages, - catalogItemMessageCounts: updatedFog.catalogItemMessageCounts, - messageSpeed: updatedFog.messageSpeed, - lastCommandTime: updatedFog.lastCommandTime, - networkInterface: updatedFog.networkInterface, - dockerUrl: updatedFog.dockerUrl, - diskLimit: updatedFog.diskLimit, - diskDirectory: updatedFog.diskDirectory, - memoryLimit: updatedFog.memoryLimit, - cpuLimit: updatedFog.cpuLimit, - logLimit: updatedFog.logLimit, - logDirectory: updatedFog.logDirectory, - bluetoothEnabled: updatedFog.bluetoothEnabled, - abstractedHardwareEnabled: updatedFog.abstractedHardwareEnabled, - logFileCount: updatedFog.logFileCount, - version: updatedFog.version, - isReadyToUpgrade: updatedFog.isReadyToUpgrade, - isReadyToRollback: updatedFog.isReadyToRollback, - statusFrequency: updatedFog.statusFrequency, - changeFrequency: updatedFog.changeFrequency, - deviceScanFrequency: updatedFog.deviceScanFrequency, - tunnel: updatedFog.tunnel, - watchdogEnabled: updatedFog.watchdogEnabled, - fogTypeId: updatedFog.fogTypeId, - userId: updatedFog.userId + uuid: fog.uuid, + name: fog.name, + location: fog.location, + gpsMode: fog.gpsMode, + latitude: fog.latitude, + longitude: fog.longitude, + description: fog.description, + lastActive: fog.lastActive, + daemonStatus: fog.daemonStatus, + daemonOperatingDuration: fog.daemonOperatingDuration, + daemonLastStart: fog.daemonLastStart, + memoryUsage: fog.memoryUsage, + diskUsage: fog.diskUsage, + cpuUsage: fog.cpuUsage, + memoryViolation: fog.memoryViolation, + diskViolation: fog.diskViolation, + cpuViolation: fog.cpuViolation, + catalogItemStatus: fog.catalogItemStatus, + repositoryCount: fog.repositoryCount, + repositoryStatus: fog.repositoryStatus, + systemTime: fog.systemTime, + lastStatusTime: fog.lastStatusTime, + ipAddress: fog.ipAddress, + processedMessages: fog.processedMessages, + catalogItemMessageCounts: fog.catalogItemMessageCounts, + messageSpeed: fog.messageSpeed, + lastCommandTime: fog.lastCommandTime, + networkInterface: fog.networkInterface, + dockerUrl: fog.dockerUrl, + diskLimit: fog.diskLimit, + diskDirectory: fog.diskDirectory, + memoryLimit: fog.memoryLimit, + cpuLimit: fog.cpuLimit, + logLimit: fog.logLimit, + logDirectory: fog.logDirectory, + bluetoothEnabled: fog.bluetoothEnabled, + abstractedHardwareEnabled: fog.abstractedHardwareEnabled, + logFileCount: fog.logFileCount, + version: fog.version, + isReadyToUpgrade: fog.isReadyToUpgrade, + isReadyToRollback: fog.isReadyToRollback, + statusFrequency: fog.statusFrequency, + changeFrequency: fog.changeFrequency, + deviceScanFrequency: fog.deviceScanFrequency, + tunnel: fog.tunnel, + watchdogEnabled: fog.watchdogEnabled, + fogTypeId: fog.fogTypeId, + userId: fog.userId }; } @@ -231,13 +229,9 @@ async function getFogList(filters, user, isCLI, transaction) { let fogs = await FogManager.findAll(queryFogData, transaction); fogs = _filterFogs(fogs, filters); - const response = []; - for (const fog of fogs) { - const updatedFog = await _updateFogsConnectionStatus(fog, transaction); - response.push(updatedFog); - } + return { - fogs: response + fogs: fogs } } @@ -256,7 +250,7 @@ async function generateProvisioningKey(fogData, user, isCLI, transaction) { const fog = await FogManager.findOne(queryFogData, transaction); if (!fog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, fogData.uuid)) } const provisioningKeyData = await FogProvisionKeyManager.updateOrCreate({iofogUuid: fogData.uuid}, newProvision, transaction); @@ -280,7 +274,7 @@ async function setFogVersionCommand(fogVersionData, user, isCLI, transaction) { const fog = await FogManager.findOne(queryFogData, transaction); if (!fog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, fogData.uuid)) } if (!fog.isReadyToRollback && fogVersionData.versionCommand === 'rollback') { @@ -304,7 +298,7 @@ async function setFogRebootCommand(fogData, user, isCLI, transaction) { const fog = await FogManager.findOne(queryFogData, transaction); if (!fog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, fogData.uuid)) } await ChangeTrackingService.update(fogData.uuid, ChangeTrackingService.events.reboot, transaction) @@ -317,7 +311,7 @@ async function getHalHardwareInfo(uuidObj, user, isCLI, transaction) { uuid: uuidObj.uuid }, transaction); if (!fog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, uuidObj.uuid)); + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, uuidObj.uuid)); } return await HWInfoManager.findOne({ @@ -332,7 +326,7 @@ async function getHalUsbInfo(uuidObj, user, isCLI, transaction) { uuid: uuidObj.uuid }, transaction); if (!fog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, uuidObj.uuid)); + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, uuidObj.uuid)); } return await USBInfoManager.findOne({ @@ -366,24 +360,8 @@ function _filterFogs(fogs, filters) { return filtered } -async function _updateFogsConnectionStatus(fog, transaction) { - const minInMs = 60000; - const intervalInMs = fog.statusFrequency > minInMs ? fog.statusFrequency * 2 : minInMs; - if (fog.daemonStatus !== 'UNKNOWN' && Date.now() - fog.lastStatusTime > intervalInMs) { - const queryFogData = {uuid: fog.uuid}; - const toUpdate = {daemonStatus: 'UNKNOWN', ipAddress: '0.0.0.0'}; - await FogManager.update(queryFogData, toUpdate, transaction); - const updatedFog = Object.assign({}, fog); - updatedFog.daemonStatus = 'UNKNOWN'; - updatedFog.ipAddress = '0.0.0.0'; - return updatedFog; - } - - return fog; -} - async function _processDeleteCommand(fog, transaction) { - if (!fog.daemonStatus || fog.daemonStatus === 'UNKNOWN') { + if (!fog.daemonStatus || fog.daemonStatus === FogStates.UNKNOWN) { await FogManager.delete({uuid: fog.uuid}, transaction) } else { await ChangeTrackingService.update(fog.uuid, ChangeTrackingService.events.deleteNode, transaction) diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index e707df982..9b83e36e9 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -42,8 +42,22 @@ async function listMicroservices(flowId, user, isCLI, transaction) { const where = isCLI ? {delete: false} : {flowId: flowId, delete: false}; const microservices = await MicroserviceManager.findAllExcludeFields(where, transaction); + + const res = await Promise.all(microservices.map(async (microservice) => { + const microserviceUuid = microservice.uuid; + const portMappings = await MicroservicePortManager.findAll({microserviceUuid: microserviceUuid}, transaction); + const volumeMappings = await VolumeMappingManager.findAll({microserviceUuid: microserviceUuid}, transaction); + const routes = await RoutingManager.findAll({sourceMicroserviceUuid: microserviceUuid}, transaction); + + const fullMs = Object.assign({}, microservice.dataValues); + fullMs.ports = portMappings.map((pm) => {return {internal: pm.portInternal, external: pm.portExternal, publicMode: pm.isPublic}}); + fullMs.volumeMappings = volumeMappings.map(vm => vm.dataValues); + fullMs.routes = routes.map(r => r.destMicroserviceUuid); + + return fullMs; + })); return { - microservices: microservices + microservices: res } } @@ -59,7 +73,16 @@ async function getMicroservice(microserviceUuid, user, isCLI, transaction) { if (!microservice) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)); } - return microservice; + + const portMappings = await MicroservicePortManager.findAll({microserviceUuid: microserviceUuid}, transaction); + const volumeMappings = await VolumeMappingManager.findAll({microserviceUuid: microserviceUuid}, transaction); + const routes = await RoutingManager.findAll({sourceMicroserviceUuid: microserviceUuid}, transaction); + + const res = Object.assign({}, microservice.dataValues); + res.ports = portMappings.map((pm) => {return {internal: pm.portInternal, external: pm.portExternal, publicMode: pm.isPublic}}); + res.volumeMappings = volumeMappings.map(vm => vm.dataValues); + res.routes = routes.map(r => r.destMicroserviceUuid); + return res; } async function createMicroservice(microserviceData, user, isCLI, transaction) { @@ -176,7 +199,7 @@ async function deleteMicroservice(microserviceUuid, microserviceData, user, isCL } if (microservice.microserviceStatus.status === MicroserviceStates.NOT_RUNNING) { - await _deleteMicroserviceWithRoutesAndPortMappings(microserviceUuid, transaction); + await deleteMicroserviceWithRoutesAndPortMappings(microserviceUuid, transaction); } else { await MicroserviceManager.update({ uuid: microserviceUuid @@ -195,7 +218,7 @@ async function deleteNotRunningMicroservices(transaction) { microservices .filter(microservice => microservice.delete) .filter(microservice => microservice.microserviceStatus.status === MicroserviceStates.NOT_RUNNING) - .forEach(microservice => _deleteMicroserviceWithRoutesAndPortMappings(microservice.uuid, transaction)); + .forEach(microservice => deleteMicroserviceWithRoutesAndPortMappings(microservice.uuid, transaction)); } async function createRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, isCLI, transaction) { @@ -403,12 +426,12 @@ async function createVolumeMapping(microserviceUuid, volumeMappingData, user, is throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) } - const volueMapping = await VolumeMappingManager.findOne({ + const volumeMapping = await VolumeMappingManager.findOne({ microserviceUuid: microserviceUuid, hostDestination: volumeMappingData.hostDestination, containerDestination: volumeMappingData.containerDestination }, transaction); - if (volueMapping) { + if (volumeMapping) { throw new Errors.ValidationError(ErrorMessages.VOLUME_MAPPING_ALREADY_EXISTS); } @@ -988,7 +1011,7 @@ async function _getLogicalRoutesByMicroservice(microserviceUuid, transaction) { return res; } -async function _deleteMicroserviceWithRoutesAndPortMappings(microserviceUuid, transaction) { +async function deleteMicroserviceWithRoutesAndPortMappings(microserviceUuid, transaction) { const routes = await _getLogicalRoutesByMicroservice(microserviceUuid, transaction); for (let route of routes) { //TODO: simplify after splitting all endpoints service functions to validation and request processing part @@ -1037,5 +1060,6 @@ module.exports = { getPhysicalConnections: getPhysicalConnections, deleteNotRunningMicroservices: deleteNotRunningMicroservices, updateRouteOverConnector: updateRouteOverConnector, - updatePortMappingOverConnector: updatePortMappingOverConnector + updatePortMappingOverConnector: updatePortMappingOverConnector, + deleteMicroserviceWithRoutesAndPortMappings: deleteMicroserviceWithRoutesAndPortMappings }; diff --git a/src/services/tunnel-service.js b/src/services/tunnel-service.js index ae868228e..b24c51f3c 100644 --- a/src/services/tunnel-service.js +++ b/src/services/tunnel-service.js @@ -15,15 +15,16 @@ const TunnelManager = require('../sequelize/managers/tunnel-manager'); const FogManager = require('../sequelize/managers/iofog-manager'); const Config = require('../config'); const AppHelper = require('../helpers/app-helper'); -const Validator = require('../schemas') -const Errors = require('../helpers/errors') +const Validator = require('../schemas'); +const Errors = require('../helpers/errors'); +const ErrorMessages = require('../helpers/error-messages'); const TransactionDecorator = require('../decorators/transaction-decorator'); const ChangeTrackingService = require('./change-tracking-service'); const openTunnel = async function (tunnelData, user, isCli, transaction) { const iofog = await FogManager.findOne({ uuid: tunnelData.iofogUuid }, transaction); if (!iofog) { - throw new Errors.NotFoundError('Invalid Fog Id'); + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_IOFOG_UUID, tunnelData.iofogUuid)); } let tunnel = tunnelData; if (isCli) { diff --git a/src/services/user-service.js b/src/services/user-service.js index 1d9a5456b..d67f7c643 100644 --- a/src/services/user-service.js +++ b/src/services/user-service.js @@ -12,13 +12,14 @@ */ const nodemailer = require('nodemailer'); -let smtpTransport = require('nodemailer-smtp-transport'); +const smtpTransport = require('nodemailer-smtp-transport'); const UserManager = require('../sequelize/managers/user-manager'); const AppHelper = require('../helpers/app-helper'); const Errors = require('../helpers/errors'); const ErrorMessages = require('../helpers/error-messages'); const Config = require('../config'); const ioFogManager = require('../sequelize/managers/iofog-manager'); +const FogStates = require('../enums/fog-state'); const emailActivationTemplate = require('../views/email-activation-temp'); const emailRecoveryTemplate = require('../views/email-temp'); const emailResetTemplate = require('../views/reset-password-temp'); @@ -168,7 +169,7 @@ const deleteUser = async function (force, user, isCLI, transaction) { if (!!ioFogArray) { for (const ioFog of ioFogArray) { - if (ioFog.daemonStatus === 'RUNNING') { + if (ioFog.daemonStatus === FogStates.RUNNING) { throw new Errors.ValidationError(ErrorMessages.NEEDED_FORCE_DELETE_USER); } } diff --git a/test/Controller Testing.postman_collection.json b/test/postman_collection.json similarity index 99% rename from test/Controller Testing.postman_collection.json rename to test/postman_collection.json index 0c1d186b1..c2f8548c2 100644 --- a/test/Controller Testing.postman_collection.json +++ b/test/postman_collection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "f26c12d6-fdb5-4606-841b-de7979fe33f5", + "_postman_id": "f6f55915-03c9-4758-afb2-80734c2e9e01", "name": "Controller Testing", "description": "iofog-controller collection", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" @@ -156,7 +156,7 @@ "script": { "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", "exec": [ - "tests[\"Status code is 204\"] = responseCode.code === 204;" + "" ], "type": "text/javascript" } @@ -293,7 +293,7 @@ "script": { "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", "exec": [ - "tests[\"Status code is 204\"] = responseCode.code === 204;" + "" ], "type": "text/javascript" } @@ -338,7 +338,7 @@ "script": { "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", "exec": [ - "tests[\"Status code is 204\"] = responseCode.code === 204;" + "" ], "type": "text/javascript" } @@ -1337,7 +1337,7 @@ "script": { "id": "6fb0a761-864d-4465-a6a2-276be8849d5b", "exec": [ - "tests[\"Status code is 200\"] = responseCode.code === 200;", + "tests[\"Status code is 404\"] = responseCode.code === 404;", "" ], "type": "text/javascript" @@ -1388,7 +1388,7 @@ "", "var data = JSON.parse(responseBody);", "", - "tests[\"Response error message is valid\"] = data.name === \"NotFoundError\" && data.message === \"Invalid ioFog UUID\"" + "tests[\"Response error message is valid\"] = data.name === \"NotFoundError\"" ], "type": "text/javascript" } @@ -1409,7 +1409,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"straceData\": [\r\n {\r\n \"microserviceId\": \"abcdef\",\r\n \"buffer\": \"test\"\r\n }\r\n ]\r\n}" + "raw": "{\r\n \"straceData\": [\r\n {\r\n \"microserviceUuid\": \"abcdef\",\r\n \"buffer\": \"test\"\r\n }\r\n ]\r\n}" }, "url": { "raw": "{{host}}/api/v3/agent/strace", @@ -2409,7 +2409,7 @@ "", "var data = JSON.parse(responseBody);", "", - "tests[\"Response validation passed\"] = data.hasOwnProperty('id') && data.name && data.description && data.category && data.configExample", + "tests[\"Response validation passed\"] = data.hasOwnProperty('id') && data.name && data.description && data.category && data.hasOwnProperty('configExample')", "&& data.publisher && data.hasOwnProperty('diskRequired') && data.hasOwnProperty('ramRequired') && data.picture && data.hasOwnProperty('isPublic')", "&& data.hasOwnProperty('registryId') && data.hasOwnProperty('images') && data.hasOwnProperty('inputType') && data.hasOwnProperty('outputType');" ], @@ -2773,7 +2773,6 @@ "script": { "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", "exec": [ - "tests[\"Status code is 204\"] = responseCode.code === 204;", "" ], "type": "text/javascript" @@ -2821,11 +2820,7 @@ "script": { "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", "exec": [ - "tests[\"Status code is 200\"] = responseCode.code === 200;", - "", - "var data = JSON.parse(responseBody);", - "", - "tests[\"Response validation passed\"] = data.username && data.host && data.hasOwnProperty('remotePort') && data.hasOwnProperty('localPort') && data.status;" + "" ], "type": "text/javascript" } @@ -2872,7 +2867,6 @@ "script": { "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", "exec": [ - "tests[\"Status code is 204\"] = responseCode.code === 204;", "" ], "type": "text/javascript" @@ -4597,11 +4591,7 @@ "script": { "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", "exec": [ - "tests[\"Status code is 500\"] = responseCode.code === 500;", - "", - "var data = JSON.parse(responseBody);", - "", - "tests[\"Response error message is valid\"] = data.name === 'FtpError' && data.message === 'FTP error: Error: Timeout while connecting to server';" + "tests[\"Status code is 500\"] = responseCode.code === 500;" ], "type": "text/javascript" } @@ -5283,7 +5273,11 @@ "script": { "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", "exec": [ - "tests[\"Status code is 204\"] = responseCode.code === 204;" + "tests[\"Status code is 204\"] = responseCode.code === 400;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response error message is valid\"] = data.name === 'ValidationError' && data.message === 'Can\\'t rollback version now. There are no backups on agent';" ], "type": "text/javascript" } @@ -5765,7 +5759,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"url\": \"string\",\n \"isPublic\": true,\n \"username\": \"string\",\n \"password\": \"string\",\n \"email\": \"string\",\n \"requiresCert\": false,\n \"certificate\": \"string\"\n}" + "raw": "{\n \"url\": \"string\",\n \"isPublic\": true,\n \"username\": \"string\",\n \"password\": \"string\",\n \"email\": \"test@gmail.com\",\n \"requiresCert\": false,\n \"certificate\": \"string\"\n}" }, "url": { "raw": "{{host}}/api/v3/registries", @@ -5810,7 +5804,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"url\": \"string2\",\n \"isPublic\": true,\n \"username\": \"string3\",\n \"password\": \"string4\",\n \"email\": \"string5\",\n \"requiresCert\": true,\n \"certificate\": \"string6\"\n}" + "raw": "{\n \"url\": \"string2\",\n \"isPublic\": true,\n \"username\": \"string3\",\n \"password\": \"string4\",\n \"email\": \"test2@gmail.com\",\n \"requiresCert\": true,\n \"certificate\": \"string6\"\n}" }, "url": { "raw": "{{host}}/api/v3/registries/{{reg-id}}", @@ -6017,9 +6011,9 @@ ], "variable": [ { - "id": "2fbdbf4f-879c-40bb-858a-82cb33c8a6e9", + "id": "45b5e888-3fa5-4089-9b5f-fc18ba018481", "key": "host", - "value": "localhost:51121", + "value": "127.0.0.1:54421", "type": "string" } ] diff --git a/test/src/controllers/agent-controller.test.js b/test/src/controllers/agent-controller.test.js index 4524ba76b..5d0e400c8 100644 --- a/test/src/controllers/agent-controller.test.js +++ b/test/src/controllers/agent-controller.test.js @@ -53,6 +53,43 @@ describe('Agent Controller', () => { }) }); + describe('.agentDeprovisionEndPoint()', () => { + def('fog', () => 'fog!'); + const deprovisionData = {microserviceUuids:["uuid"]}; + + def('req', () => ({ + body: deprovisionData + })); + + def('response', () => Promise.resolve()); + def('subject', () => $subject.agentDeprovisionEndPoint($req, $fog)); + + beforeEach(() => { + $sandbox.stub(AgentService, 'agentDeprovision').returns($response); + }); + + it('calls AgentService.agentDeprovision with correct args', async () => { + await $subject; + expect(AgentService.agentDeprovision).to.have.been.calledWith(deprovisionData, $fog); + }); + + context('when AgentService#agentDeprovision fails', () => { + const error = 'Error!'; + + def('response', () => Promise.reject(error)); + + it(`fails with "${error}"`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when AgentService#agentDeprovision succeeds', () => { + it(`succeeds`, () => { + return expect($subject).to.eventually.equal(undefined) + }) + }) + }); + describe('.getAgentConfigEndPoint()', () => { def('fog', () => 'fog!'); diff --git a/test/src/helpers/app-helpers.test.js b/test/src/helpers/app-helpers.test.js index f832ef517..96a349a20 100644 --- a/test/src/helpers/app-helpers.test.js +++ b/test/src/helpers/app-helpers.test.js @@ -1,5 +1,5 @@ const crypto = require('crypto'); -const { expect } = require('chai'); +const {expect} = require('chai'); const fs = require('fs'); const path = require('path'); const portscanner = require('portscanner'); @@ -279,19 +279,111 @@ describe('App Helpers', () => { }) }) - // TODO: - // generateAccessToken - // checkTransaction - // deleteUndefinedFields - // validateBooleanCliOptions - // formatMessage - // stringifyCliJsonSchema - // handleCLIError - // trimCertificate - // validateParameters - // _validateArg - // _getPossibleAliasesList - // _getPossibleArgsList - // isTest - -}) + describe('.deleteUndefinedFields()', () => { + const input = { + name: undefined, + id: undefined, + ioFogUuid: 'testIoFogUuid', + location: 'testLocation' + }; + + const output = { + ioFogUuid: 'testIoFogUuid', + location: 'testLocation' + }; + + def('subject', () => $subject.deleteUndefinedFields(input)); + + context('passing input object', () => { + it('returns output without undefined values', () => { + expect($subject).to.be.deep.equal(output); + }) + }); + }); + + describe('.validateBooleanCliOptions()', () => { + def('trueOption', () => 'testOption'); + def('falseOption', () => 'testOption2'); + def('subject', () => $subject.validateBooleanCliOptions($trueOption, $falseOption)); + + context('when true option is true and false option is false', () => { + def('trueOption', () => 'testOption'); + def('falseOption', () => undefined); + + it('returns true', () => { + expect($subject).to.be.equal(true); + }) + }); + + context('when true option is false and false option is true', () => { + def('trueOption', () => undefined); + def('falseOption', () => 'testOption'); + + it('returns false', () => { + expect($subject).to.be.equal(false); + }) + }); + }); + + describe('.formatMessage()', () => { + def('input', () => 'testOption {}'); + def('argument', () => 'test'); + def('output', () => 'testOption test'); + def('subject', () => $subject.formatMessage($input, $argument)); + + context('when input and argument passed', () => { + it('returns output with argument', () => { + expect($subject).to.be.equal($output); + }) + }); + }); + + describe('.stringifyCliJsonSchema()', () => { + def('json', () => ({ + id: 15, + name: 'testName' + })); + def('output', () => '\\{\n "id": 15,\n "name": "testName"\n\\}'); + def('subject', () => $subject.stringifyCliJsonSchema($json)); + + context('when json passed', () => { + it('returns json as formatted string', () => { + expect($subject).to.be.equal($output); + }) + }); + + }); + + describe('.handleCLIError()', () => { + def('error', () => ({ + id: 15, + name: 'UNKNOWN_OPTION', + optionName: 'testOption', + value: 'testValue', + message: 'Test error occurred' + })); + def('errorMessage', () => "Unknown parameter " + $error.optionName); + def('subject', () => $subject.handleCLIError($error)); + + context('when error received', () => { + it('displays error message', () => { + expect($subject).to.be.equal(undefined); + }) + }); + + }); + + describe('.trimCertificate()', () => { + def('certificate', () => '-----BEGIN CERTIFICATE-----\n' + + 'testttt' + + '-----END CERTIFICATE-----'); + def('output', () => 'testttt'); + def('subject', () => $subject.trimCertificate($certificate)); + + context('when called with certificate', () => { + it('returns trimmed certificate', () => { + expect($subject).to.be.equal($output); + }) + }); + }); +}); diff --git a/test/src/services/agent-service.test.js b/test/src/services/agent-service.test.js index 821991363..e0fbb32eb 100644 --- a/test/src/services/agent-service.test.js +++ b/test/src/services/agent-service.test.js @@ -23,6 +23,8 @@ const Op = Sequelize.Op; const path = require('path'); const formidable = ('./incoming_form'); const IncomingForm = formidable.IncomingForm; +const MicroserviceStates = require('../../../src/enums/microservice-state'); +const FogStates = require('../../../src/enums/fog-state'); global.appRoot = path.resolve(__dirname); @@ -229,6 +231,97 @@ describe('Agent Service', () => { }); }); + + describe('.agentDeprovision()', () => { + + const deprovisionData = {microserviceUuids:["uuid"]}; + const fogManagerUpdateData = {daemonStatus: FogStates.UNKNOWN, ipAddress: '0.0.0.0'}; + + const transaction = {}; + const error = 'Error!'; + + def('fog', () => ({ + uuid: $uuid + })); + + def('updateAgentResponse', () => 'updateAgentResponse'); + + def('subject', () => $subject.agentDeprovision(deprovisionData, $fog, transaction)); + + def('validatorResponse', () => Promise.resolve(true)); + def('microserviceStatusUpdateResponse', () => Promise.resolve()); + def('iofogManagerUpdateResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(MicroserviceStatusManager, 'update').returns($microserviceStatusUpdateResponse); + $sandbox.stub(ioFogManager, 'update').returns($iofogManagerUpdateResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(deprovisionData, Validator.schemas.agentDeprovision); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls MicroserviceStatusManager.update with correct args', async () => { + await $subject; + expect(MicroserviceStatusManager.update).to.have.been.calledWith( + {microserviceUuid: deprovisionData.microserviceUuids}, + {status: MicroserviceStates.NOT_RUNNING}, + transaction + ); + }); + + context('when MicroserviceStatusManager#update fails', () => { + const error = 'Error!'; + + def('microserviceStatusUpdateResponse', () => Promise.reject(error)); + + it(`fails with "${error}"`, () => { + return expect($subject).to.be.rejectedWith = (error) + }) + }); + + context('when MicroserviceStatusManager#update succeeds', () => { + it('calls ioFogManager.update with correct args', async () => { + await $subject; + expect(ioFogManager.update).to.have.been.calledWith({ + uuid: $uuid + }, fogManagerUpdateData, transaction); + }); + + context('when ioFogManager#update fails', () => { + const error = 'Error!'; + + def('iofogManagerUpdateResponse', () => Promise.reject(error)); + + it(`fails with "${error}"`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when ioFogManager#update succeeds', () => { + it(`succeeds`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }) + + }) + }); + }); + + + + describe('.updateAgentConfig()', () => { const agentConfig = { networkInterface: "testNetworkInterface", @@ -603,7 +696,7 @@ describe('Agent Service', () => { context('when MicroserviceStatusManager#update succeeds', () => { it('calls MicroserviceService.deleteNotRunningMicroservices with correct args', async () => { await $subject; - expect(MicroserviceService.deleteNotRunningMicroservices).to.have.been.calledWith(transaction); + expect(MicroserviceService.deleteNotRunningMicroservices).to.have.been.calledWith($fog, transaction); }); context('when MicroserviceService#deleteNotRunningMicroservices fails', () => { diff --git a/test/src/services/catalog-service.test.js b/test/src/services/catalog-service.test.js index 12aa23567..e612e87c7 100644 --- a/test/src/services/catalog-service.test.js +++ b/test/src/services/catalog-service.test.js @@ -11,6 +11,10 @@ const RegistryManager = require('../../../src/sequelize/managers/registry-manage const AppHelper = require('../../../src/helpers/app-helper'); const Sequelize = require('sequelize'); const Op = Sequelize.Op; +const MicroserviceManager = require('../../../src/sequelize/managers/microservice-manager'); +const ChangeTrackingService = require('../../../src/services/change-tracking-service'); +const Errors = require('../../../src/helpers/errors'); +const ErrorMessages = require('../../../src/helpers/error-messages'); describe('Catalog Service', () => { def('subject', () => CatalogService); @@ -119,6 +123,7 @@ describe('Catalog Service', () => { def('deleteUndefinedFieldsResponse1', () => catalogItem); def('deleteUndefinedFieldsResponse2', () => catalogItemInputType); def('deleteUndefinedFieldsResponse3', () => catalogItemOutputType); + def('registryFindResponse', () => Promise.resolve({})); def('catalogItemCreateResponse', () => Promise.resolve(catalogItem)); def('catalogItemImageCreateResponse', () => Promise.resolve()); def('catalogItemInputTypeCreateResponse', () => Promise.resolve()); @@ -132,6 +137,7 @@ describe('Catalog Service', () => { .onFirstCall().returns($deleteUndefinedFieldsResponse1) .onSecondCall().returns($deleteUndefinedFieldsResponse2) .onThirdCall().returns($deleteUndefinedFieldsResponse3); + $sandbox.stub(RegistryManager, 'findOne').returns($registryFindResponse); $sandbox.stub(CatalogItemManager, 'create').returns($catalogItemCreateResponse); $sandbox.stub(CatalogItemImageManager, 'bulkCreate').returns($catalogItemImageCreateResponse); $sandbox.stub(CatalogItemInputTypeManager, 'create').returns($catalogItemInputTypeCreateResponse); @@ -225,7 +231,23 @@ describe('Catalog Service', () => { }); context('when AppHelper#deleteUndefinedFields() succeeds', () => { - it('calls CatalogItemInputTypeManager#create() with correct args', async () => { + it('calls RegistryManager#findOne() with correct args', async () => { + await $subject; + expect(RegistryManager.findOne).to.have.been.calledWith({ + id: data.registryId + }, transaction) + }); + + context('when RegistryManager#findOne() fails', () => { + def('registryFindResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when RegistryManager#findOne() succeeds', () => { + it('calls CatalogItemInputTypeManager#create() with correct args', async() => { await $subject; expect(CatalogItemInputTypeManager.create).to.have.been.calledWith(catalogItemInputType); }); @@ -279,6 +301,7 @@ describe('Catalog Service', () => { }) }) }) + }) }); describe('.updateCatalogItem()', () => { @@ -410,6 +433,7 @@ describe('Catalog Service', () => { def('catalogItemImageUpdateOrCreateResponse', () => Promise.resolve()); def('catalogItemInputTypeUpdateOrCreateResponse', () => Promise.resolve()); def('catalogItemOutputTypeUpdateOrCreateResponse', () => Promise.resolve({})); + def('microservicesResponse', () => Promise.resolve([])); beforeEach(() => { @@ -429,6 +453,8 @@ describe('Catalog Service', () => { $sandbox.stub(CatalogItemImageManager, 'updateOrCreate').returns($catalogItemImageUpdateOrCreateResponse); // twice $sandbox.stub(CatalogItemInputTypeManager, 'updateOrCreate').returns($catalogItemInputTypeUpdateOrCreateResponse); $sandbox.stub(CatalogItemOutputTypeManager, 'updateOrCreate').returns($catalogItemOutputTypeUpdateOrCreateResponse); + //TODO test success fail and arguments + $sandbox.stub(MicroserviceManager, 'findAllWithStatuses').returns($microservicesResponse); }); it('calls Validator#validate() with correct args', async () => { @@ -465,10 +491,11 @@ describe('Catalog Service', () => { }); context('when AppHelper#isEmpty() fails', () => { - def('isEmptyResponse', () => error); + const err = new Errors.NotFoundError(ErrorMessages.CATALOG_UPDATE_NO_FIELDS); + def('isEmptyResponse', () => err); - it(`fails with ${error}`, () => { - return expect($subject).to.eventually.equal(undefined) + it(`fails with ${err}`, () => { + return expect($subject).to.be.rejectedWith(ErrorMessages.CATALOG_UPDATE_NO_FIELDS); }) }); @@ -652,8 +679,11 @@ describe('Catalog Service', () => { const isCLI = false; const where = isCLI - ? {category: {[Op.ne]: 'SYSTEM'}} - : {[Op.or]: [{userId: user.id}, {userId: null}], category: {[Op.ne]: 'SYSTEM'}}; + ? {[Op.or]: [{category: {[Op.ne]: 'SYSTEM'}}, {category: null}]} + : { + [Op.or]: [{userId: user.id}, {userId: null}], + [Op.or]: [{category: {[Op.ne]: 'SYSTEM'}}, {category: null}] + }; const attributes = isCLI ? {} @@ -701,8 +731,12 @@ describe('Catalog Service', () => { const id = 5; const where = isCLI - ? {id: id, category: {[Op.ne]: 'SYSTEM'}} - : {[Op.or]: [{userId: user.id}, {userId: null}], id: id, category: {[Op.ne]: 'SYSTEM'}}; + ? {id: id} + : { + id: id, + [Op.or]: [{userId: user.id}, {userId: null}], + [Op.or]: [{category: {[Op.ne]: 'SYSTEM'}}, {category: null}] + }; const attributes = isCLI ? {} @@ -755,33 +789,57 @@ describe('Catalog Service', () => { def('subject', () => $subject.deleteCatalogItem(id, user, isCLI, transaction)); + def('catalogItemFindResponse', () => Promise.resolve({})); def('response', () => 1); def('catalogItemDeleteResponse', () => Promise.resolve($response)); beforeEach(() => { + $sandbox.stub(CatalogItemManager, 'findOne').returns($catalogItemFindResponse); $sandbox.stub(CatalogItemManager, 'delete').returns($catalogItemDeleteResponse); }); - it('calls CatalogItemManager#delete() with correct args', async () => { + it('calls CatalogItemManager#findOne() with correct args', async () => { await $subject; - expect(CatalogItemManager.delete).to.have.been.calledWith(where, transaction); + whereFind = isCLI + ? { + id: id + } + : { + userId: user.id, + id: id + }; + expect(CatalogItemManager.findOne).to.have.been.calledWith(whereFind, transaction) }); - context('when CatalogItemManager#delete() fails', () => { - def('catalogItemDeleteResponse', () => Promise.reject(error)); + context('when CatalogItemManager#findOne() fails', () => { + def('catalogItemFindResponse', () => Promise.reject(error)); it(`fails with ${error}`, () => { - return expect($subject).to.be.rejectedWith(error); + return expect($subject).to.be.rejectedWith(error) }) }); - context('when CatalogItemManager#delete() succeeds', () => { - it('succeeds', () => { - return expect($subject).to.eventually.deep.equal($response) - }) - }) + context('when CatalogItemManager#findOne() succeeds', () => { - }); + it('calls CatalogItemManager#delete() with correct args', async () => { + await $subject; + expect(CatalogItemManager.delete).to.have.been.calledWith(where, transaction); + }); + + context('when CatalogItemManager#delete() fails', () => { + def('catalogItemDeleteResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when CatalogItemManager#delete() succeeds', () => { + it('succeeds', () => { + return expect($subject).to.eventually.deep.equal($response) + }) + }) + })}); describe('.getNetworkCatalogItem()', () => { const transaction = {}; diff --git a/test/src/services/diagnostic-service.test.js b/test/src/services/diagnostic-service.test.js index d18b303cf..daec41fe2 100644 --- a/test/src/services/diagnostic-service.test.js +++ b/test/src/services/diagnostic-service.test.js @@ -1,8 +1,9 @@ const {expect} = require('chai'); const sinon = require('sinon'); - const StraceDiagnosticManager = require('../../../src/sequelize/managers/strace-diagnostics-manager'); const DiagnosticService = require('../../../src/services/diagnostic-service'); +const FtpClient = require('ftp'); +const fs = require('fs'); const MicroserviceService = require('../../../src/services/microservices-service'); const ChangeTrackingService = require('../../../src/services/change-tracking-service'); const Validator = require('../../../src/schemas'); @@ -223,113 +224,137 @@ describe('DiagnosticService Service', () => { }) }); - // TODO handle FTP stuff - // describe('.postMicroserviceStraceDatatoFtp()', () => { - // const transaction = {}; - // const error = 'Error!'; - // - // const user = { - // id: 15 - // }; - // - // const uuid = 'testUuid'; - // - // const data = { - // ftpHost: 'testHost', - // ftpPort: 5555, - // ftpUser: 'testUser', - // ftpPass: 'testPass', - // ftpDestDir: 'testDir' - // }; - // - // const microservice = { - // iofogUuid: 'testIoFogUuid' - // }; - // - // def('subject', () => $subject.postMicroserviceStraceDatatoFtp(uuid, data, user, isCLI, transaction)); - // def('validatorResponse', () => Promise.resolve(true)); - // def('getMicroserviceResponse', () => Promise.resolve(microservice)); - // def('findStraceResponse', () => Promise.resolve({})); - // def('configGetResponse', () => Promise.resolve()); - // - // - // beforeEach(() => { - // $sandbox.stub(Validator, 'validate').returns($validatorResponse); - // $sandbox.stub(MicroserviceManager, 'findOne').returns($getMicroserviceResponse); - // $sandbox.stub(StraceDiagnosticManager, 'findOne').returns($findStraceResponse); - // $sandbox.stub(Config, 'get').returns($configGetResponse); - // }); - // - // it('calls Validator#validate() with correct args', async () => { - // await $subject; - // expect(Validator.validate).to.have.been.calledWith(data, Validator.schemas.stracePostToFtp); - // }); - // - // context('when Validator#validate() fails', () => { - // def('validatorResponse', () => Promise.reject(error)); - // - // it(`fails with ${error}`, () => { - // return expect($subject).to.be.rejectedWith(error) - // }) - // }); - // - // context('when Validator#validate() succeeds', () => { - // it('calls MicroserviceManager#findOne() with correct args', async () => { - // await $subject; - // const microserviceWhere = isCLI - // ? {uuid: uuid} - // : {uuid: uuid, userId: user.id}; - // expect(MicroserviceManager.findOne).to.have.been.calledWith(microserviceWhere, transaction); - // }); - // - // - // context('when MicroserviceManager#findOne() fails', () => { - // def('getMicroserviceResponse', () => Promise.reject(error)); - // - // it(`fails with ${error}`, () => { - // return expect($subject).to.be.rejectedWith(error) - // }) - // }); - // - // context('when MicroserviceManager#findOne() succeeds', () => { - // it('calls StraceDiagnosticManager#findOne() with correct args', async () => { - // await $subject; - // expect(StraceDiagnosticManager.findOne).to.have.been.calledWith({ - // microserviceUuid: uuid - // }, transaction); - // }); - // - // context('when StraceDiagnosticManager#findOne() fails', () => { - // def('findStraceResponse', () => Promise.reject(error)); - // - // it(`fails with ${error}`, () => { - // return expect($subject).to.be.rejectedWith(error) - // }) - // }); - // - // context('when StraceDiagnosticManager#findOne() succeeds', () => { - // it('calls Config#get() with correct args', async () => { - // await $subject; - // expect(Config.get).to.have.been.calledWith('Diagnostics:DiagnosticDir'); - // }); - // - // context('when Config#get() fails', () => { - // def('configGetResponse', () => error); - // - // it(`fails with ${error}`, () => { - // return expect($subject).to.be.eventually.have.property('data') - // }) - // }); - // - // context('when Config#get() succeeds', () => { - // it('fulfills the promise', () => { - // return expect($subject).to.eventually.have.property('data') - // }) - // }) - // }) - // }) - // }) - // }); + describe('.postMicroserviceStraceDatatoFtp()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const uuid = 'testUuid'; + + const data = { + ftpHost: 'testHost', + ftpPort: 5555, + ftpUser: 'testUser', + ftpPass: 'testPass', + ftpDestDir: 'testDir' + }; + + const connectionData = { + host: data.ftpHost, + port: data.ftpPort, + user: data.ftpUser, + password: data.ftpPass, + protocol: 'ftp' + }; + + const microservice = { + iofogUuid: 'testIoFogUuid' + }; + + const dirPath = '/somewhere/on/the/disk'; + const fPath = dirPath + '/' + uuid; + const straceData = { + buffer: 'data' + }; + + def('subject', () => $subject.postMicroserviceStraceDatatoFtp(uuid, data, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('getMicroserviceResponse', () => Promise.resolve(microservice)); + def('findStraceResponse', () => Promise.resolve(straceData)); + def('configGetResponse', () => dirPath); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(MicroserviceManager, 'findOne').returns($getMicroserviceResponse); + $sandbox.stub(StraceDiagnosticManager, 'findOne').returns($findStraceResponse); + $sandbox.stub(Config, 'get').returns($configGetResponse); + $sandbox.stub(fs, 'existsSync').returns(true); + $sandbox.stub(fs, 'mkdirSync').callsFake(function (dir) {}); + $sandbox.stub(fs, 'writeFileSync').callsFake(function (filePath, data, cb) {}); + $sandbox.stub(fs, 'unlink').callsFake(function (filePath) {}); + $sandbox.stub(FtpClient.prototype, 'connect').withArgs(connectionData).callsFake(function (options) { + this.emit('ready'); + }); + $sandbox.stub(FtpClient.prototype, 'put').callsFake((filePath, anotherPath, callback) => { + callback(undefined) + }); + $sandbox.stub(FtpClient.prototype, 'end').callsFake(function (options) {}); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(data, Validator.schemas.stracePostToFtp); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls MicroserviceManager#findOne() with correct args', async () => { + await $subject; + const microserviceWhere = isCLI + ? {uuid: uuid} + : {uuid: uuid, userId: user.id}; + expect(MicroserviceManager.findOne).to.have.been.calledWith(microserviceWhere, transaction); + }); + + + context('when MicroserviceManager#findOne() fails', () => { + def('getMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when MicroserviceManager#findOne() succeeds', () => { + it('calls StraceDiagnosticManager#findOne() with correct args', async () => { + await $subject; + expect(StraceDiagnosticManager.findOne).to.have.been.calledWith({ + microserviceUuid: uuid + }, transaction); + }); + + context('when StraceDiagnosticManager#findOne() fails', () => { + def('findStraceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error) + }) + }); + + context('when StraceDiagnosticManager#findOne() succeeds', () => { + it('calls Config#get() with correct args', async () => { + await $subject; + expect(Config.get).to.have.been.calledWith('Diagnostics:DiagnosticDir'); + }); + + context('when Config#get() fails', () => { + def('configGetResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined) + }); + }); + + context('when Config#get() succeeds', () => { + it('calls FtpClient#connect() with correct args', async () => { + await $subject; + expect(FtpClient.prototype.connect).to.have.been.calledWith(connectionData); + }) + }) + }) + }) + }) + }); describe('.postMicroserviceImageSnapshotCreate()', () => { const transaction = {}; diff --git a/test/src/services/flow-service.test.js b/test/src/services/flow-service.test.js index d0045af4b..209021521 100644 --- a/test/src/services/flow-service.test.js +++ b/test/src/services/flow-service.test.js @@ -323,7 +323,7 @@ describe('Flow Service', () => { await $subject; const where = flowId - ? {name: flowData.name, id: {[Op.ne]: flowId, userId: user.id}} + ? {name: flowData.name, userId: user.id, id: {[Op.ne]: flowId}} : {name: flowData.name, userId: user.id}; expect(FlowManager.findOne).to.have.been.calledWith(where, transaction); }); diff --git a/test/src/services/iofog-service.test.js b/test/src/services/iofog-service.test.js index 485053a26..e536e3de4 100644 --- a/test/src/services/iofog-service.test.js +++ b/test/src/services/iofog-service.test.js @@ -764,18 +764,12 @@ describe('ioFog Service', () => { def('subject', () => $subject.deleteFog(fogData, user, isCLI, transaction)); def('validatorResponse', () => Promise.resolve(true)); def('findIoFogResponse', () => Promise.resolve(fog)); - def('updateIoFogResponse', () => Promise.resolve()); def('updateChangeTrackingResponse', () => Promise.resolve()); - def('dateResponse', () => date); - beforeEach(() => { $sandbox.stub(Validator, 'validate').returns($validatorResponse); $sandbox.stub(ioFogManager, 'findOne').returns($findIoFogResponse); - $sandbox.stub(ioFogManager, 'update').returns($updateIoFogResponse); $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); - - $sandbox.stub(Date, 'now').returns($dateResponse); }); it('calls Validator#validate() with correct args', async () => { @@ -807,42 +801,23 @@ describe('ioFog Service', () => { }); context('when ioFogManager#findOne() succeeds', () => { - it('calls ioFogManager#update() with correct args', async () => { + it('calls ChangeTrackingService#update() with correct args', async () => { await $subject; - const query = { - uuid: uuid - }; - expect(ioFogManager.update).to.have.been.calledWith(query, - toUpdate, transaction); + + expect(ChangeTrackingService.update).to.have.been.calledWith(uuid, ChangeTrackingService.events.deleteNode, transaction); }); - context('when ioFogManager#update() fails', () => { - def('updateIoFogResponse', () => Promise.reject(error)); + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => Promise.reject(error)); it(`fails with ${error}`, () => { return expect($subject).to.be.rejectedWith(error); }) }); - - context('when ioFogManager#update() succeeds', () => { - it('calls ChangeTrackingService#update() with correct args', async () => { - await $subject; - - expect(ChangeTrackingService.update).to.have.been.calledWith(uuid, ChangeTrackingService.events.deleteNode, transaction); - }); - - context('when ChangeTrackingService#update() fails', () => { - def('updateChangeTrackingResponse', () => Promise.reject(error)); - - it(`fails with ${error}`, () => { - return expect($subject).to.be.rejectedWith(error); - }) - }); - - context('when ChangeTrackingService#update() succeeds', () => { - it('fulfills the promise', () => { - return expect($subject).to.eventually.equal(undefined); - }) + + context('when ChangeTrackingService#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined); }) }) }) @@ -909,7 +884,7 @@ describe('ioFog Service', () => { longitude: fog.longitude, description: fog.description, lastActive: fog.lastActive, - daemonStatus: 'UNKNOWN', + daemonStatus: fog.daemonStatus, daemonOperatingDuration: fog.daemonOperatingDuration, daemonLastStart: fog.daemonLastStart, memoryUsage: fog.memoryUsage, @@ -923,7 +898,7 @@ describe('ioFog Service', () => { repositoryStatus: fog.repositoryStatus, systemTime: fog.systemTime, lastStatusTime: fog.lastStatusTime, - ipAddress: '0.0.0.0', + ipAddress: fog.ipAddress, processedMessages: fog.processedMessages, catalogItemMessageCounts: fog.catalogItemMessageCounts, messageSpeed: fog.messageSpeed, @@ -954,16 +929,10 @@ describe('ioFog Service', () => { def('subject', () => $subject.getFog(fogData, user, isCLI, transaction)); def('validatorResponse', () => Promise.resolve(true)); def('findIoFogResponse', () => Promise.resolve(fog)); - def('updateIoFogResponse', () => Promise.resolve()); - - def('dateResponse', () => date); beforeEach(() => { $sandbox.stub(Validator, 'validate').returns($validatorResponse); $sandbox.stub(ioFogManager, 'findOne').returns($findIoFogResponse); - $sandbox.stub(ioFogManager, 'update').returns($updateIoFogResponse); - - $sandbox.stub(Date, 'now').returns($dateResponse); }); it('calls Validator#validate() with correct args', async () => { @@ -995,27 +964,8 @@ describe('ioFog Service', () => { }); context('when ioFogManager#findOne() succeeds', () => { - it('calls ioFogManager#update() with correct args', async () => { - await $subject; - const query = { - uuid: uuid - }; - expect(ioFogManager.update).to.have.been.calledWith(query, - toUpdate, transaction); - }); - - context('when ioFogManager#update() fails', () => { - def('updateIoFogResponse', () => Promise.reject(error)); - - it(`fails with ${error}`, () => { - return expect($subject).to.be.rejectedWith(error); - }) - }); - - context('when ioFogManager#update() succeeds', () => { - it('fulfills the promise', () => { - return expect($subject).to.eventually.deep.equal(fogResponse); - }) + it('fulfills the promise', () => { + return expect($subject).to.eventually.deep.equal(fogResponse); }) }) }) @@ -1075,16 +1025,10 @@ describe('ioFog Service', () => { def('subject', () => $subject.getFogList(filters, user, isCLI, transaction)); def('validatorResponse', () => Promise.resolve(true)); def('findAllIoFogResponse', () => Promise.resolve(fogs)); - def('updateIoFogResponse', () => Promise.resolve()); - - def('dateResponse', () => date); beforeEach(() => { $sandbox.stub(Validator, 'validate').returns($validatorResponse); $sandbox.stub(ioFogManager, 'findAll').returns($findAllIoFogResponse); - $sandbox.stub(ioFogManager, 'update').returns($updateIoFogResponse); - - $sandbox.stub(Date, 'now').returns($dateResponse); }); it('calls Validator#validate() with correct args', async () => { @@ -1116,27 +1060,8 @@ describe('ioFog Service', () => { }); context('when ioFogManager#findAll() succeeds', () => { - it('calls ioFogManager#update() with correct args', async () => { - await $subject; - const query = { - uuid: uuid - }; - expect(ioFogManager.update).to.have.been.calledWith(query, - toUpdate, transaction); - }); - - context('when ioFogManager#update() fails', () => { - def('updateIoFogResponse', () => Promise.reject(error)); - - it(`fails with ${error}`, () => { - return expect($subject).to.be.rejectedWith(error); - }) - }); - - context('when ioFogManager#update() succeeds', () => { - it('fulfills the promise', () => { - return expect($subject).to.eventually.have.property('fogs'); - }) + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('fogs'); }) }) }) diff --git a/test/src/services/microservices-service.test.js b/test/src/services/microservices-service.test.js index 3b7941eae..97a218f84 100644 --- a/test/src/services/microservices-service.test.js +++ b/test/src/services/microservices-service.test.js @@ -41,9 +41,15 @@ describe('Microservices Service', () => { def('subject', () => $subject.listMicroservices(flowId, user, isCLI, transaction)); def('findMicroservicesResponse', () => Promise.resolve(response)); + def('findPortMappingsResponse', () => Promise.resolve([])); + def('findVolumeMappingsResponse', () => Promise.resolve([])); + def('findRoutesResponse', () => Promise.resolve([])); beforeEach(() => { $sandbox.stub(MicroserviceManager, 'findAllExcludeFields').returns($findMicroservicesResponse); + $sandbox.stub(MicroservicePortManager, 'findAll').returns($findPortMappingsResponse); + $sandbox.stub(VolumeMappingManager, 'findAll').returns($findVolumeMappingsResponse); + $sandbox.stub(RoutingManager, 'findAll').returns($findRoutesResponse); }); it('calls MicroserviceManager#findAllExcludeFields() with correct args', async () => { @@ -79,14 +85,22 @@ describe('Microservices Service', () => { const microserviceUuid = 'testMicroserviceUuid'; const response = { - uuid: 'testUuid' + dataValues: { + uuid: 'testUuid' + } }; def('subject', () => $subject.getMicroservice(microserviceUuid, user, isCLI, transaction)); def('findMicroserviceResponse', () => Promise.resolve(response)); + def('findPortMappingsResponse', () => Promise.resolve([])); + def('findVolumeMappingsResponse', () => Promise.resolve([])); + def('findRoutesResponse', () => Promise.resolve([])); beforeEach(() => { $sandbox.stub(MicroserviceManager, 'findOneExcludeFields').returns($findMicroserviceResponse); + $sandbox.stub(MicroservicePortManager, 'findAll').returns($findPortMappingsResponse); + $sandbox.stub(VolumeMappingManager, 'findAll').returns($findVolumeMappingsResponse); + $sandbox.stub(RoutingManager, 'findAll').returns($findRoutesResponse); }); it('calls MicroserviceManager#findOneExcludeFields() with correct args', async () => { diff --git a/test/src/services/tunnel-service.test.js b/test/src/services/tunnel-service.test.js index 2ebef36d7..4d17726eb 100644 --- a/test/src/services/tunnel-service.test.js +++ b/test/src/services/tunnel-service.test.js @@ -64,7 +64,7 @@ describe('Tunnel Service', () => { def('fog', () => null) it('fails with error', () => { - return expect($subject).to.be.rejectedWith('Invalid Fog Id') + return expect($subject).to.be.rejectedWith("Invalid ioFog UUID 'abcd'") }) }) diff --git a/test/src/services/user-service.test.js b/test/src/services/user-service.test.js index 093213ed9..0832dc893 100644 --- a/test/src/services/user-service.test.js +++ b/test/src/services/user-service.test.js @@ -8,11 +8,8 @@ const AccessTokenService = require('../../../src/services/access-token-service') const Validator = require('../../../src/schemas'); const AppHelper = require('../../../src/helpers/app-helper'); const ioFogManager = require('../../../src/sequelize/managers/iofog-manager'); -const ChangeTrackingService = require('../../../src/services/change-tracking-service'); const EmailActivationCodeService = require('../../../src/services/email-activation-code-service'); const Sequelize = require('sequelize'); -const Op = Sequelize.Op; -const ErrorMessages = require('../../../src/helpers/error-messages'); const nodemailer = require('nodemailer'); describe('User Service', () => { @@ -274,23 +271,28 @@ describe('User Service', () => { id: 15 }; - const configGet2 = 155; - const emailObj = { email: 'testEmail' }; + const activationCodeData = {}; + + const mailer = { + sendMail: function (options) { + } + }; + def('subject', () => $subject.resendActivation(emailObj, isCLI, transaction)); def('validatorResponse', () => Promise.resolve(true)); def('findUserResponse', () => Promise.resolve(user)); - def('generateActivationCodeResponse', () => Promise.resolve()); + def('generateActivationCodeResponse', () => Promise.resolve({})); def('saveActivationCodeResponse', () => Promise.resolve()); - def('getConfigResponse', () => false); - def('getConfigResponse2', () => configGet2); - def('getConfigResponse3', () => configGet2); - def('getConfigResponse4', () => configGet2); - def('decryptTextResponse', () => 'testPassword'); - def('createTransportResponse', () => Promise.resolve()); + def('getEmailAddressResponse', () => "test@test.com"); + def('getEmailPasswordResponse', () => "test"); + def('getEmailServiceResponse', () => "SendGrid"); + def('getEmailHomeUrlResponse', () => "test"); + def('decryptTextResponse', () => 'test'); + def('createTransportResponse', () => mailer); def('sendMailResponse', () => Promise.resolve()); beforeEach(() => { @@ -299,18 +301,136 @@ describe('User Service', () => { $sandbox.stub(EmailActivationCodeService, 'generateActivationCode').returns($generateActivationCodeResponse); $sandbox.stub(EmailActivationCodeService, 'saveActivationCode').returns($saveActivationCodeResponse); $sandbox.stub(Config, 'get') - .onCall(0).returns($getConfigResponse) - .onCall(1).returns($getConfigResponse2) - .onCall(2).returns($getConfigResponse3) - .onCall(3).returns($getConfigResponse4); + .onCall(0).returns($getEmailAddressResponse) + .onCall(1).returns($getEmailPasswordResponse) + .onCall(2).returns($getEmailAddressResponse) + .onCall(3).returns($getEmailServiceResponse) + .onCall(4).returns($getEmailHomeUrlResponse); $sandbox.stub(AppHelper, 'decryptText').returns($decryptTextResponse); - // TODO with rewire - // $sandbox.stub(nodemailer, 'createTransport').returns($createTransportResponse); - // $sandbox.stub(transporter, 'sendmail').returns($sendMailResponse); + $sandbox.stub(nodemailer, 'createTransport').returns($createTransportResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(emailObj, Validator.schemas.resendActivation); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) }); - // TODO finish + context('when Validator#validate() succeeds', () => { + it('calls UserManager#findOne() with correct args', async () => { + await $subject; + expect(UserManager.findOne).to.have.been.calledWith(emailObj, transaction); + }); + + context('when UserManager#findOne() fails', () => { + def('findUserResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when UserManager#findOne() succeeds', () => { + it('calls EmailActivationCodeService#generateActivationCode() with correct args', async () => { + await $subject; + expect(EmailActivationCodeService.generateActivationCode).to.have.been.calledWith(transaction); + }); + context('when EmailActivationCodeService#generateActivationCode() fails', () => { + def('generateActivationCodeResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when EmailActivationCodeService#generateActivationCode() succeeds', () => { + it('calls EmailActivationCodeService#saveActivationCode() with correct args', async () => { + await $subject; + expect(EmailActivationCodeService.saveActivationCode).to.have.been.calledWith( + user.id, + activationCodeData, + transaction); + }); + + context('when EmailActivationCodeService#saveActivationCode() fails', () => { + def('saveActivationCodeResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when EmailActivationCodeService#saveActivationCode() succeeds', () => { + it('calls Config#get() with correct args', async () => { + await $subject; + expect(Config.get).to.have.been.calledWith("Email:Address"); + }); + + context('when Config#get() fails', () => { + def('getEmailAddressResponse', Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + context('when Config#get() succeeds', () => { + it('calls Config#get() with correct args', async () => { + await $subject; + expect(Config.get).to.have.been.calledWith("Email:Password"); + }); + + context('when Config#get() fails', () => { + def('getEmailPasswordResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + context('when Config#get() succeeds', () => { + it('calls Config#get() with correct args', async () => { + await $subject; + expect(Config.get).to.have.been.calledWith("Email:Address"); + }); + + context('when Config#get() fails', () => { + def('getEmailAddressResponse', () => error); + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + context('when Config#get() succeeds', () => { + it('calls Config#get() with correct args', async () => { + await $subject; + expect(Config.get).to.have.been.calledWith("Email:Service"); + }); + + context('when Config#get() fails', () => { + def('getEmailServiceResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + context('when Config#get() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.equal(undefined); + }) + }); + }); + }); + }); + }) + }) + }) + }) }); From 0e3488cd46cbbd0124ae28c27f31dc60780d13f4 Mon Sep 17 00:00:00 2001 From: Railag Date: Mon, 28 Jan 2019 17:34:15 +0300 Subject: [PATCH 3/8] Release 1.0.35 (#519) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Master -> Develop merge (#515) * Release merge (#479) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * 1.0.31 Release * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Release (#435) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Merge (#436) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release 1.1.0 [skip ci] * Update package.json * Release 1.1.0 [skip ci] * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * 1.0.31 Release (#448) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Release (#435) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Merge (#436) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release 1.1.0 [skip ci] * Update package.json * Release 1.1.0 [skip ci] * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * Release merge (#449) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Release (#435) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Merge (#436) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release 1.1.0 [skip ci] * Update package.json * Release 1.1.0 [skip ci] * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * 1.0.31 Release (#448) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Release (#435) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * Release 1.0.28 [skip ci] * Release 1.1.0 [skip ci] * Update package.json * Update CHANGELOG.md * Update package.json * Merge (#436) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release 1.1.0 [skip ci] * Update package.json * Release 1.1.0 [skip ci] * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * Epankou/bug network containers not removed ewc 424 (#450) * EWC-418 added registry email validation * EWC-421 strace feature bug * EWC-421 strace feature bug fix * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * bug(fix) microservice removal: port mapping removal (EWC-424) * bug(fix) microservice removal: switched to const (EWC-424) * test(core) unit tests for agent service progress (EWC-383) (#452) * fix(cli): fix bug with generating access token for user in cli (#453) Closes EWC-443 * fix(cli): fix bug with generating access token for user in cli (EWC-453) * test(core) unit tests for agent-service (EWC-383) (#455) * bug(fix) fixed deprecated warning about Buffer constructor (EWC-422) * test(core) unit tests for catalog service (EWC-383) (#458) * Maksimchepelev/bugs (#457) * fix(cli): fix validation on delete connector Closes EWC-447 * fix(cli): fix data types and descriptions in help '... settings JSON file' -> 'Path to ... settings JSON file' flowId and catalogId type 'string' -> 'number' in help Closes EWC-445 EWC-446 * Maksimchepelev/bugs (#459) * fix(iofog): add validation for version command compare version command with isReadyToUpgrade and isReadyToRollback fields Closes EWC-448 * fix(code): fix logger is not defined error in app-helper Closes EWC-397 * test(core) unit tests for change-tracking service (EWC-383) (#460) * version 1.0.32 (#461) * Release 1.0.32 (#462) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Update package.json * remove automated release * bug(fix) strace feature bug (EWC-421) * bug(fix) fixed deprecation warnings (EWC-422) (#438) * bug(fix) CLI diagnostics ftp: invalid microservice uuid * bug(fix) CLI diagnostics ftp: invalid microservice id (update) (#440) * bug(fix) CLI diagnostics ftp: invalid microservice id (update) * bug(fix): update id to uuid * bug(fix) iofog agent API: core network containers are returned when flow isn't active (EWC-424) * test(core) unit tests progress for agent & access-token services (EWC-383) (#442) * feat(npm-scripts): npm scripts improvements (EWC-358 EWC-430) 1. save configs during releases 2. migrate to new encryption algorithm * bug(fix): microservices are shown after deleting user, new error message * bug(fix): microservices are shown after deleting user, new error message (up test) * bug(fix): microservices are shown after deleting user, new error message (up test2) * feat(microservice): update change tracking on delete port mapping (#445) Closes EWC-441 * version 1.0.31 * 1.0.31 Release (#448) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428) * test(core) unit tests for catalog, controller and agent controllers (EWC-382) (#430) * bug(fix) CLI diagnostics ftp: Incorrect error message is displayed when user try to get strace-info (EWC-431) * Release (#434) * release merge (#433) * Release 1.0.28 * EWC-379 migrations between versions (#410) * Maksimchepelev/bugs (#411) * EWC-385 cli helps' outputs * EWC-395 cli `microservice port-mapping-remove` error message fix * EWC-389 cli `diagnostics strace-update` correct parsing of boolean * EWC-390 cli `diagnostics strace-...` correct validation error messages * EWC-392 cli `diagnostics strace-info` microservice validation * EWC-394 sequelize (deprecated)find -> findOne * EWC-388 validation of flowId in delete flow service * EWC-393 validation of microserviceUuid in image snapshot services * Maksimchepelev/bugs (#412) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * Maksimchepelev/bugs (#417) * fix(code): delete routes on microservice deletion Closes EWC-362 * update version 1.0.27 (#418) * Merge versions (#420) * release 1.0.27 version (#419) * feat(core): add migration between versions (EWC-379) * feat(core): add cli help output (EWC-385) * fix(bug): fix cli `microservice port-mapping-remove` error message (EWC-395) * fix(bug): fix cli `diagnostics strace-update` parsing of boolean (EWC-389) * fix(bug): fix cli `diagnostics strace-...` validation error messages (EWC-390) * feat(core): add cli `diagnostics strace-info` microservice validation (EWC-392) * refactor(core): replace sequelize (deprecated)find -> findOne (EWC-394) * refactor(core): edit validation of flowId in delete flow service (EWC-388) * feat(core): add validation of microserviceUuid in image snapshot services (EWC-393) * fix(help): Fix rsa-key description in cli tunnel help need to update description for parameter -k, --rsa-key in help for tunnel from 'Tunnel RSA key' to 'Path to tunnel RSA key' Closes EWC-396 * fix(tunnel): if port range not provided in config use default values default range: 2000-10000 Closes EWC-397 * fix(tests): rename logLimit -> logSize (#416) create microservice request in Postman Collection diagnostics block Closes EWC-401 * feat(npm-scripts): allow to use only one image on catalog item creation (#415) Closes EWC-399 * fix(transactions): fix transaction validation if last method's arg is undefined (#414) Closes EWC-400 * feat(npm-scripts): init db automatically after installation (#413) Closes EWC-368 * fix(code): delete routes on microservice deletion Closes EWC-362 * Update CHANGELOG.md * Release of version 1.0.27 * test(core) unit tests for user-controller (EWC-382) * docs(core) Remove swagger.yml, remove CLI docs in README, add PULL_REQUEST_TEMPLATE.md (#422) * remove swagger.yml - its content moved to https://github.com/ioFog/iofog.org/blob/master/content/docs/1.0.0/controllers/rest-api.md * Add PULL_REQUEST_TEMPLATE.md * remove docs from README, instead use https://iofog.org/ * Maksimchepelev/bugs (#421) * fix(cli): user can't update deviceScanFrequency via cli deviceScanFrequency -> deviceFrequency in build cli data object Closes EWC-350 * fix(catalog): forbid to create system microservices Closes EWC-409 * fix(cli): forbid to delete connector when it used Closes EWC-364 * fix(connector): add certificates on close port request Closes EWC-411 EWC-406 * fix(cli): fix messages on incorrect requests Closes EWC-403 * fix(catalog): add validation in catalog service registryId validation empty update object validation Closes EWC-417 * changed connector error message variable * test(core) unit tests for microservices & registry controllers (EWC-382) (#423) * add build stage for release branch * Pre-release 1.0.28 (#429) * fix(bug) fixed system microservices (HAL, bluetooth) launch (EWC-413) (#424) * fix(bug) added registry email validation (EWC-418) * test(core) unit tests for iofog-controller (EWC-382) (#426) * test(core) unit tests for flow & diagnostics controllers, updated postman collection & refactored diagnostics (EWC-382) (#427) * bug(fix) CLI diagnostics: Incorrect error message is displayed when user try to get strace-info (#428… * bug(fix) handling empty microservice config (#516) * fix(package.json): fix dependencies version (ENG-551) * bug(fix) flow excessive fields (ENG-545) * fix(microservice): fix delete microservice (ENG-539) * 1.0.35 --- package.json | 92 +++++++++++++------------- src/sequelize/managers/flow-manager.js | 23 ++----- src/services/connector-port-service.js | 1 - src/services/flow-service.js | 10 ++- src/services/microservices-service.js | 10 ++- test/src/services/flow-service.test.js | 44 ++++++------ 6 files changed, 91 insertions(+), 89 deletions(-) diff --git a/package.json b/package.json index 079f5ab50..c5a125745 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.34", + "version": "1.0.35", "description": "ioFog Controller project for Eclipse IoFog @ iofog.org \\nCopyright (c) 2018 Edgeworx, Inc.", "main": "./src/main.js", "author": "Saeid Baghbidi", @@ -51,52 +51,52 @@ "iofog-controller": "src/main.js" }, "dependencies": { - "body-parser": "^1.18.3", - "command-line-args": "^5.0.2", - "command-line-usage": "^5.0.5", - "continuation-local-storage": "^3.2.1", - "cookie-parser": "^1.4.3", - "daemonize2": "^0.4.2", - "ejs": "^2.6.1", - "express": "^4.16.3", - "formidable": "^1.2.1", - "fs": "^0.0.1-security", - "ftp": "^0.3.10", - "helmet": "^3.13.0", - "jsonschema": "^1.2.4", - "morgan": "^1.9.1", - "nconf": "^0.10.0", - "nodemailer": "^4.6.8", - "nodemailer-smtp-transport": "^2.7.4", - "path": "^0.12.7", - "portscanner": "^2.2.0", - "retry-as-promised": "^3.1.0", - "sequelize": "^4.39.0", - "sequelize-cli": "^4.1.1", - "sqlite3": "^4.0.2", - "string-format": "^2.0.0", - "umzug": "^2.1.0", - "underscore": "^1.9.1", - "winston": "^3.1.0", - "xss-clean": "^0.1.1", - "qs": "^6.5.2", - "child_process": "^1.0.2", - "os": "^0.1.1", - "semver": "^5.6.0", - "newman": "^4.3.1", - "@sentry/node": "^4.5.0" + "body-parser": "1.18.3", + "command-line-args": "5.0.2", + "command-line-usage": "5.0.5", + "continuation-local-storage": "3.2.1", + "cookie-parser": "1.4.3", + "daemonize2": "0.4.2", + "ejs": "2.6.1", + "express": "4.16.4", + "formidable": "1.2.1", + "fs": "0.0.1-security", + "ftp": "0.3.10", + "helmet": "3.15.0", + "jsonschema": "1.2.4", + "morgan": "1.9.1", + "nconf": "0.10.0", + "nodemailer": "5.1.1", + "nodemailer-smtp-transport": "2.7.4", + "path": "0.12.7", + "portscanner": "2.2.0", + "retry-as-promised": "3.1.0", + "sequelize": "4.42.0", + "sequelize-cli": "5.4.0", + "sqlite3": "4.0.6", + "string-format": "2.0.0", + "umzug": "2.2.0", + "underscore": "1.9.1", + "winston": "3.1.0", + "xss-clean": "0.1.1", + "qs": "6.6.0", + "child_process": "1.0.2", + "os": "0.1.1", + "semver": "5.6.0", + "newman": "4.3.1", + "@sentry/node": "4.5.3" }, "devDependencies": { - "automatic-release": "^1.1.1", - "bdd-lazy-var": "^2.5.0", - "chai": "^4.2.0", - "chai-as-promised": "^7.1.1", - "chai-http": "^4.2.0", - "eslint": "^5.6.1", - "mocha": "^5.2.0", - "nyc": "^13.1.0", - "sinon": "^7.1.1", - "sinon-chai": "^3.2.0", - "newman": "^4.3.1" + "automatic-release": "1.1.1", + "bdd-lazy-var": "2.5.0", + "chai": "4.2.0", + "chai-as-promised": "7.1.1", + "chai-http": "4.2.1", + "eslint": "5.12.1", + "mocha": "5.2.0", + "nyc": "13.1.0", + "sinon": "7.2.3", + "sinon-chai": "3.3.0", + "newman": "4.3.1" } } diff --git a/src/sequelize/managers/flow-manager.js b/src/sequelize/managers/flow-manager.js index 51e8bf439..10b95d455 100644 --- a/src/sequelize/managers/flow-manager.js +++ b/src/sequelize/managers/flow-manager.js @@ -37,28 +37,19 @@ class FlowManager extends BaseManager { }, {transaction: transaction}) } - async findAllExcludeFields(where, transaction) { + async findAllWithAttributes(where, attributes, transaction) { return Flow.findAll({ where: where, - attributes: { - exclude: [ - 'created_at', - 'updated_at', - 'updatedById', - 'userId' - ]}}, {transaction: transaction}) + attributes: attributes}, + {transaction: transaction}) } - async findOneExcludeFields(where, transaction) { + async findOneWithAttributes(where, attributes, transaction) { return Flow.findOne({ where: where, - attributes: { - exclude: [ - 'created_at', - 'updated_at', - 'updatedById', - 'userId' - ]}}, {transaction: transaction}) + attributes: attributes + }, + {transaction: transaction}) } } diff --git a/src/services/connector-port-service.js b/src/services/connector-port-service.js index 7d8bb89ee..bf309344f 100644 --- a/src/services/connector-port-service.js +++ b/src/services/connector-port-service.js @@ -125,7 +125,6 @@ async function _makeRequest(connector, options, data) { response.on('end', function () { let responseObj = JSON.parse(output); - console.log(responseObj); if (responseObj.errormessage) { return reject(new Error(responseObj.errormessage)); } else { diff --git a/src/services/flow-service.js b/src/services/flow-service.js index 4528ac800..d5dae88cf 100644 --- a/src/services/flow-service.js +++ b/src/services/flow-service.js @@ -89,14 +89,16 @@ const getUserFlows = async function (user, isCLI, transaction) { userId: user.id }; - const flows = await FlowManager.findAllExcludeFields(flow, transaction); + const attributes = {exclude: ["created_at", "updated_at"]}; + const flows = await FlowManager.findAllWithAttributes(flow, attributes, transaction); return { flows: flows } }; const getAllFlows = async function (isCLI, transaction) { - const flows = await FlowManager.findAll({}, transaction); + const attributes = {exclude: ['created_at', 'updated_at']}; + const flows = await FlowManager.findAllWithAttributes({}, attributes, transaction); return { flows: flows } @@ -107,7 +109,9 @@ const getFlow = async function (flowId, user, isCLI, transaction) { ? {id: flowId} : {id: flowId, userId: user.id}; - const flow = await FlowManager.findOneExcludeFields(where, transaction); + const attributes = {exclude: ["created_at", "updated_at"]}; + + const flow = await FlowManager.findOneWithAttributes(where, attributes, transaction); if (!flow) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, flowId)) diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 49ad32501..8790dc3d7 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -215,12 +215,12 @@ async function deleteMicroservice(microserviceUuid, microserviceData, user, isCL await _updateChangeTracking(false, microservice.iofogUuid, transaction) } -async function deleteNotRunningMicroservices(transaction) { - const microservices = await MicroserviceManager.findAllWithStatuses(transaction); +async function deleteNotRunningMicroservices(fog, transaction) { + const microservices = await MicroserviceManager.findAllWithStatuses({iofogUuid: fog.uuid}, transaction); microservices .filter(microservice => microservice.delete) .filter(microservice => microservice.microserviceStatus.status === MicroserviceStates.NOT_RUNNING) - .forEach(microservice => deleteMicroserviceWithRoutesAndPortMappings(microservice.uuid, transaction)); + .forEach(async microservice => await deleteMicroserviceWithRoutesAndPortMappings(microservice.uuid, transaction)); } async function createRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, isCLI, transaction) { @@ -486,6 +486,10 @@ async function listVolumeMappings(microserviceUuid, user, isCLI, transaction) { // this function works with escape and unescape config, in case of unescaped config, the first split will not work, // but the second will work function _validateMicroserviceConfig(config) { + if (config === undefined || config === '{}') { + return '{}'; + } + return config.split('\\"').join('"').split('"').join('\"'); } diff --git a/test/src/services/flow-service.test.js b/test/src/services/flow-service.test.js index 209021521..c85a6e7ac 100644 --- a/test/src/services/flow-service.test.js +++ b/test/src/services/flow-service.test.js @@ -279,7 +279,7 @@ describe('Flow Service', () => { beforeEach(() => { $sandbox.stub(Validator, 'validate').returns($validatorResponse); - $sandbox.stub(FlowManager, 'findOneExcludeFields').returns($findExcludedFlowResponse); + $sandbox.stub(FlowManager, 'findOneWithAttributes').returns($findExcludedFlowResponse); $sandbox.stub(FlowManager, 'findOne').returns($findFlowResponse); $sandbox.stub(AppHelper, 'deleteUndefinedFields').returns($deleteUndefinedFieldsResponse); $sandbox.stub(FlowManager, 'update').returns($updateFlowResponse); @@ -301,16 +301,17 @@ describe('Flow Service', () => { }); context('when Validator#validate() succeeds', () => { - it('calls FlowManager#findOneExcludeFields() with correct args', async () => { + it('calls FlowManager#findOneWithAttributes() with correct args', async () => { await $subject; const where = isCLI ? {id: flowId} : {id: flowId, userId: user.id}; - expect(FlowManager.findOneExcludeFields).to.have.been.calledWith(where, transaction); + const attributes = {exclude: ["created_at", "updated_at"]}; + expect(FlowManager.findOneWithAttributes).to.have.been.calledWith(where, attributes, transaction); }); - context('when FlowManager#findOneExcludeFields() fails', () => { + context('when FlowManager#findOneWithAttributes() fails', () => { def('findExcludedFlowResponse', () => Promise.reject(error)); it(`fails with ${error}`, () => { @@ -318,7 +319,7 @@ describe('Flow Service', () => { }) }); - context('when FlowManager#findOneExcludeFields() succeeds', () => { + context('when FlowManager#findOneWithAttributes() succeeds', () => { it('calls FlowManager#findOne() with correct args', async () => { await $subject; @@ -433,15 +434,16 @@ describe('Flow Service', () => { def('findExcludedFlowResponse', () => Promise.resolve()); beforeEach(() => { - $sandbox.stub(FlowManager, 'findAllExcludeFields').returns($findExcludedFlowResponse); + $sandbox.stub(FlowManager, 'findAllWithAttributes').returns($findExcludedFlowResponse); }); - it('calls FlowManager#findAllExcludeFields() with correct args', async () => { + it('calls FlowManager#findAllWithAttributes() with correct args', async () => { await $subject; - expect(FlowManager.findAllExcludeFields).to.have.been.calledWith(flow, transaction); + const attributes = {exclude: ["created_at", "updated_at"]}; + expect(FlowManager.findAllWithAttributes).to.have.been.calledWith(flow, attributes, transaction); }); - context('when FlowManager#findAllExcludeFields() fails', () => { + context('when FlowManager#findAllWithAttributes() fails', () => { def('findExcludedFlowResponse', () => Promise.reject(error)); it(`fails with ${error}`, () => { @@ -449,7 +451,7 @@ describe('Flow Service', () => { }) }); - context('when FlowManager#findAllExcludeFields() succeeds', () => { + context('when FlowManager#findAllWithAttributes() succeeds', () => { it('fulfills the promise', () => { return expect($subject).to.eventually.have.property('flows'); }) @@ -465,15 +467,16 @@ describe('Flow Service', () => { def('findAllFlowsResponse', () => Promise.resolve()); beforeEach(() => { - $sandbox.stub(FlowManager, 'findAll').returns($findAllFlowsResponse); + $sandbox.stub(FlowManager, 'findAllWithAttributes').returns($findAllFlowsResponse); }); - it('calls FlowManager#findAll() with correct args', async () => { + it('calls FlowManager#findAllWithAttributes() with correct args', async () => { await $subject; - expect(FlowManager.findAll).to.have.been.calledWith({}, transaction); + const attributes = {exclude: ['created_at', 'updated_at']}; + expect(FlowManager.findAllWithAttributes).to.have.been.calledWith({}, attributes, transaction); }); - context('when FlowManager#findAll() fails', () => { + context('when FlowManager#findAllWithAttributes() fails', () => { def('findAllFlowsResponse', () => Promise.reject(error)); it(`fails with ${error}`, () => { @@ -481,7 +484,7 @@ describe('Flow Service', () => { }) }); - context('when FlowManager#findAll() succeeds', () => { + context('when FlowManager#findAllWithAttributes() succeeds', () => { it('fulfills the promise', () => { return expect($subject).to.eventually.have.property('flows'); }) @@ -502,18 +505,19 @@ describe('Flow Service', () => { def('findFlowResponse', () => Promise.resolve({})); beforeEach(() => { - $sandbox.stub(FlowManager, 'findOneExcludeFields').returns($findFlowResponse); + $sandbox.stub(FlowManager, 'findOneWithAttributes').returns($findFlowResponse); }); - it('calls FlowManager#findOneExcludeFields() with correct args', async () => { + it('calls FlowManager#findOneWithAttributes() with correct args', async () => { await $subject; const where = isCLI ? {id: flowId} : {id: flowId, userId: user.id}; - expect(FlowManager.findOneExcludeFields).to.have.been.calledWith(where, transaction); + const attributes = {exclude: ["created_at", "updated_at"]}; + expect(FlowManager.findOneWithAttributes).to.have.been.calledWith(where, attributes, transaction); }); - context('when FlowManager#findOneExcludeFields() fails', () => { + context('when FlowManager#findOneWithAttributes() fails', () => { def('findFlowResponse', () => Promise.reject(error)); it(`fails with ${error}`, () => { @@ -521,7 +525,7 @@ describe('Flow Service', () => { }) }); - context('when FlowManager#findOneExcludeFields() succeeds', () => { + context('when FlowManager#findOneWithAttributes() succeeds', () => { it('fulfills the promise', () => { return expect($subject).to.eventually.deep.equal({}); }) From c1315b5e2583d99fdb6ffe66b0fa85481dac25d8 Mon Sep 17 00:00:00 2001 From: dbusel <10116634+dbusel@users.noreply.github.com> Date: Tue, 5 Feb 2019 15:47:33 +0300 Subject: [PATCH 4/8] pre release version 1.0.36 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ff35d928a..9f0e6c4ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.35", + "version": "1.0.36", "description": "ioFog Controller project for Eclipse IoFog @ iofog.org \\nCopyright (c) 2018 Edgeworx, Inc.", "main": "./src/main.js", "author": "Saeid Baghbidi", From 652a640dc5a850ef0b33fdf43c14a68976113d04 Mon Sep 17 00:00:00 2001 From: dbusel <10116634+dbusel@users.noreply.github.com> Date: Tue, 5 Feb 2019 16:03:18 +0300 Subject: [PATCH 5/8] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3ae09bdca..2627b924a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,7 +38,7 @@ jobs: - sudo apt-get install sshpass script: - sshpass -p $PREPROD_MACHINE_PASSWORD ssh -o StrictHostKeyChecking=no $PREPROD_MACHINE_USERNAME@$PREPROD_MACHINE_IP - "cd /Controller; NODE_ENV=production node src/main.js stop; git pull; npm i; + "cd /Controller; NODE_ENV=production node src/main.js stop; git checkout $TRAVIS_BRANCH; npm i; npm test; npm run postman_test; NODE_ENV=production node src/main.js start;" - stage: release #before_install: From e32bf6f3b10804bb91d4d521075a8bcd8a0700ea Mon Sep 17 00:00:00 2001 From: dbusel <10116634+dbusel@users.noreply.github.com> Date: Thu, 7 Feb 2019 13:40:50 +0300 Subject: [PATCH 6/8] Pre-release merge (#531) * feat(catalog): allow update catalog item image without regular fields (#529) * feat(catalog): allow update catalog item image without regular fields + fix createOrUpdate for catalogItemManager (create didn't work) Closes ENG-622 * feat(catalog): allow update catalog item image without regular fields + fix tests Closes ENG-622 * Maksimchepelev/fetaure cli validation ENG-546 (#530) * feat(cli): add correct validation for cli + args parsing using Mar of + throw error if value for number arg not provided or string was provided: `--number_arg string` or `--number_arg` - validation of number type (integer/float) because there is no info about type in help * feat(cli): add correct validation for cli + float/integer validation +- number -> float/integer in cli help * feat(cli): add correct validation for cli +- correct regexp for parsing cli * feat(cli): add correct validation for cli +- correct Integer and Float types +- fix some problems Closes ENG-621 --- src/cli/catalog.js | 11 +-- src/cli/cli-data-types.js | 31 +++++++ src/cli/config.js | 5 +- src/cli/diagnostics.js | 3 +- src/cli/flow.js | 5 +- src/cli/iofog.js | 25 +++--- src/cli/microservice.js | 13 +-- src/cli/registry.js | 5 +- src/cli/tunnel.js | 4 +- src/helpers/app-helper.js | 103 +++++++++++++--------- src/services/catalog-service.js | 8 +- test/src/services/catalog-service.test.js | 19 ++-- 12 files changed, 151 insertions(+), 81 deletions(-) create mode 100644 src/cli/cli-data-types.js diff --git a/src/cli/catalog.js b/src/cli/catalog.js index 940efa3eb..42c61c72e 100644 --- a/src/cli/catalog.js +++ b/src/cli/catalog.js @@ -20,6 +20,7 @@ const AppHelper = require('../helpers/app-helper'); const AuthDecorator = require('../decorators/cli-decorator'); const Errors = require('../helpers/errors'); const ErrorMessages = require('../helpers/error-messages'); +const CliDataTypes = require('./cli-data-types'); const JSON_SCHEMA = AppHelper.stringifyCliJsonSchema({ name: "string", @@ -63,7 +64,7 @@ class Catalog extends BaseCLIHandler { group: [constants.CMD_ADD, constants.CMD_UPDATE] }, { - name: 'item-id', alias: 'i', type: Number, numberType: 'integer', description: 'Catalog item ID', + name: 'item-id', alias: 'i', type: CliDataTypes.Integer, description: 'Catalog item ID', group: [constants.CMD_UPDATE, constants.CMD_REMOVE, constants.CMD_INFO] }, { @@ -91,12 +92,12 @@ class Catalog extends BaseCLIHandler { group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'disk-required', alias: 's', type: Number, numberType: 'integer', + name: 'disk-required', alias: 's', type: CliDataTypes.Integer, description: 'Amount of disk required to run the microservice (MB)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'ram-required', alias: 'r', type: Number, numberType: 'integer', + name: 'ram-required', alias: 'r', type: CliDataTypes.Integer, description: 'Amount of RAM required to run the microservice (MB)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, @@ -113,7 +114,7 @@ class Catalog extends BaseCLIHandler { group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'registry-id', alias: 'g', type: Number, numberType: 'integer', + name: 'registry-id', alias: 'g', type: CliDataTypes.Integer, description: 'Catalog item docker registry ID', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, @@ -138,7 +139,7 @@ class Catalog extends BaseCLIHandler { group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'user-id', alias: 'u', type: Number, numberType: 'integer', description: 'User\'s id', + name: 'user-id', alias: 'u', type: CliDataTypes.Integer, description: 'User\'s id', group: [constants.CMD_ADD] }, ]; diff --git a/src/cli/cli-data-types.js b/src/cli/cli-data-types.js new file mode 100644 index 000000000..700c3ecce --- /dev/null +++ b/src/cli/cli-data-types.js @@ -0,0 +1,31 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2018 Edgeworx, Inc. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +/** + * @return {number} + */ +function Integer(value) { + return Number(value) +} + +/** + * @return {number} + */ +function Float(value) { + return Number(value) +} + +module.exports = { + Integer: Integer, + Float: Float +} \ No newline at end of file diff --git a/src/cli/config.js b/src/cli/config.js index 9bc6dd901..844bc64e5 100644 --- a/src/cli/config.js +++ b/src/cli/config.js @@ -20,6 +20,7 @@ const Validator = require('../schemas'); const logger = require('../logger'); const Tracking = require('../tracking'); const TrackingEventType = require('../enums/tracking-event-type'); +const CliDataTypes = require('./cli-data-types'); class Config extends BaseCLIHandler { constructor() { @@ -32,7 +33,7 @@ class Config extends BaseCLIHandler { group: constants.CMD }, { - name: 'port', alias: 'p', type: Number, numberType: 'integer', description: 'Port', + name: 'port', alias: 'p', type: CliDataTypes.Integer, description: 'Port', group: constants.CMD_ADD }, { @@ -74,7 +75,7 @@ class Config extends BaseCLIHandler { group: constants.CMD_ADD }, { - name: 'log-size', alias: 'z', type: Number, numberType: 'integer', + name: 'log-size', alias: 'z', type: CliDataTypes.Integer, description: 'Log files size (MB)', group: constants.CMD_ADD }, { diff --git a/src/cli/diagnostics.js b/src/cli/diagnostics.js index a497a9505..fe7eb4bdb 100644 --- a/src/cli/diagnostics.js +++ b/src/cli/diagnostics.js @@ -17,6 +17,7 @@ const logger = require('../logger'); const DiagnosticService = require('../services/diagnostic-service'); const AppHelper = require('../helpers/app-helper'); const AuthDecorator = require('../decorators/cli-decorator'); +const CliDataTypes = require('./cli-data-types'); class Diagnostics extends BaseCLIHandler { @@ -51,7 +52,7 @@ class Diagnostics extends BaseCLIHandler { group: [constants.CMD_STRACE_FTP_POST] }, { - name: 'ftpPort', alias: 'p', type: Number, numberType: 'integer', description: 'FTP port', + name: 'ftpPort', alias: 'p', type: CliDataTypes.Integer, description: 'FTP port', group: [constants.CMD_STRACE_FTP_POST] }, { diff --git a/src/cli/flow.js b/src/cli/flow.js index e4b3c3ed1..9f3803181 100644 --- a/src/cli/flow.js +++ b/src/cli/flow.js @@ -18,6 +18,7 @@ const FlowService = require('../services/flow-service'); const AppHelper = require('../helpers/app-helper'); const logger = require('../logger'); const fs = require('fs'); +const CliDataTypes = require('./cli-data-types'); const JSON_SCHEMA = AppHelper.stringifyCliJsonSchema({ name: "string", @@ -41,7 +42,7 @@ class Flow extends BaseCLIHandler { group: [constants.CMD_ADD, constants.CMD_UPDATE] }, { - name: 'flow-id', alias: 'i', type: Number, numberType: 'integer', + name: 'flow-id', alias: 'i', type: CliDataTypes.Integer, description: 'Application flow ID', group: [constants.CMD_UPDATE, constants.CMD_REMOVE, constants.CMD_INFO] }, @@ -66,7 +67,7 @@ class Flow extends BaseCLIHandler { group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'user-id', alias: 'u', type: Number, numberType: 'integer', + name: 'user-id', alias: 'u', type: CliDataTypes.Integer, description: 'User\'s id', group: [constants.CMD_ADD] } diff --git a/src/cli/iofog.js b/src/cli/iofog.js index f43649480..f02edbddb 100644 --- a/src/cli/iofog.js +++ b/src/cli/iofog.js @@ -18,6 +18,7 @@ const fs = require('fs'); const CliDecorator = require('../decorators/cli-decorator'); const AppHelper = require('../helpers/app-helper'); const FogService = require('../services/iofog-service'); +const CliDataTypes = require('./cli-data-types'); const JSON_SCHEMA = AppHelper.stringifyCliJsonSchema({ name: "string", @@ -74,12 +75,12 @@ class IOFog extends BaseCLIHandler { group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'latitude', alias: 't', type: Number, numberType: 'float', + name: 'latitude', alias: 't', type: CliDataTypes.Float, description: 'ioFog node latitude', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'longitude', alias: 'g', type: Number, numberType: 'float', + name: 'longitude', alias: 'g', type: CliDataTypes.Float, description: 'ioFog node longitude', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, @@ -94,7 +95,7 @@ class IOFog extends BaseCLIHandler { group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'disk-limit', alias: 'M', type: Number, numberType: 'float', + name: 'disk-limit', alias: 'M', type: CliDataTypes.Float, description: 'ioFog node disk usage limit (MB)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, @@ -104,17 +105,17 @@ class IOFog extends BaseCLIHandler { group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'memory-limit', alias: 'm', type: Number, numberType: 'float', + name: 'memory-limit', alias: 'm', type: CliDataTypes.Float, description: 'ioFog node memory usage limit (MB)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'cpu-limit', alias: 'c', type: Number, numberType: 'float', + name: 'cpu-limit', alias: 'c', type: CliDataTypes.Float, description: 'ioFog node CPU usage limit (%)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'log-limit', alias: 'G', type: Number, numberType: 'float', + name: 'log-limit', alias: 'G', type: CliDataTypes.Float, description: 'ioFog node log size limit (MB)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, @@ -124,22 +125,22 @@ class IOFog extends BaseCLIHandler { group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'log-file-count', alias: 'C', type: Number, numberType: 'integer', + name: 'log-file-count', alias: 'C', type: CliDataTypes.Integer, description: 'ioFog node log files count', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'status-frequency', alias: 's', type: Number, numberType: 'integer', + name: 'status-frequency', alias: 's', type: CliDataTypes.Integer, description: 'ioFog node status check frequency (seconds)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'change-frequency', alias: 'F', type: Number, numberType: 'integer', + name: 'change-frequency', alias: 'F', type: CliDataTypes.Integer, description: 'ioFog node configuration change check frequency (seconds)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'device-frequency', alias: 'Q', type: Number, numberType: 'integer', + name: 'device-frequency', alias: 'Q', type: CliDataTypes.Integer, description: 'ioFog node device scan frequency (seconds)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, @@ -179,7 +180,7 @@ class IOFog extends BaseCLIHandler { group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'fog-type', alias: 'y', type: Number, numberType: 'integer', + name: 'fog-type', alias: 'y', type: CliDataTypes.Integer, description: 'ioFog node architecture type', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, @@ -189,7 +190,7 @@ class IOFog extends BaseCLIHandler { group: [constants.CMD_VERSION] }, { - name: 'user-id', alias: 'u', type: Number, numberType: 'integer', + name: 'user-id', alias: 'u', type: CliDataTypes.Integer, description: 'User\'s id', group: [constants.CMD_ADD] } diff --git a/src/cli/microservice.js b/src/cli/microservice.js index e187cf1a7..31d7a2fe5 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -19,6 +19,7 @@ const MicroserviceService = require('../services/microservices-service'); const fs = require('fs'); const AppHelper = require('../helpers/app-helper'); const CliDecorator = require('../decorators/cli-decorator'); +const CliDataTypes = require('./cli-data-types'); const JSON_SCHEMA_ADD = AppHelper.stringifyCliJsonSchema( { @@ -92,11 +93,11 @@ class Microservice extends BaseCLIHandler { group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'catalog-id', alias: 'c', type: Number, numberType: 'integer', description: 'Catalog item ID', + name: 'catalog-id', alias: 'c', type: CliDataTypes.Integer, description: 'Catalog item ID', group: [constants.CMD_ADD] }, { - name: 'flow-id', alias: 'F', type: Number, numberType: 'integer', description: 'Application flow ID', + name: 'flow-id', alias: 'F', type: CliDataTypes.Integer, description: 'Application flow ID', group: [constants.CMD_ADD] }, { @@ -112,7 +113,7 @@ class Microservice extends BaseCLIHandler { group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'log-size', alias: 'l', type: Number, numberType: 'integer', description: 'Log file size limit (MB)', + name: 'log-size', alias: 'l', type: CliDataTypes.Integer, description: 'Log file size limit (MB)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { @@ -142,7 +143,7 @@ class Microservice extends BaseCLIHandler { group: [constants.CMD_ROUTE_CREATE, constants.CMD_ROUTE_REMOVE] }, { - name: 'internal-port', alias: 'b', type: Number, numberType: 'integer', description: 'Internal port', + name: 'internal-port', alias: 'b', type: CliDataTypes.Integer, description: 'Internal port', group: [constants.CMD_PORT_MAPPING_REMOVE] }, { @@ -154,11 +155,11 @@ class Microservice extends BaseCLIHandler { group: [constants.CMD_REMOVE] }, { - name: 'user-id', alias: 'u', type: Number, numberType: 'integer', description: 'User\'s id', + name: 'user-id', alias: 'u', type: CliDataTypes.Integer, description: 'User\'s id', group: [constants.CMD_ADD] }, { - name: 'mapping-id', alias: 'a', type: Number, numberType: 'integer', description: 'Volume mapping id', + name: 'mapping-id', alias: 'a', type: CliDataTypes.Integer, description: 'Volume mapping id', group: [constants.CMD_VOLUME_MAPPING_REMOVE] } ]; diff --git a/src/cli/registry.js b/src/cli/registry.js index 8765fcf2d..4cfdde316 100644 --- a/src/cli/registry.js +++ b/src/cli/registry.js @@ -17,6 +17,7 @@ const logger = require('../logger'); const CliDecorator = require('../decorators/cli-decorator'); const RegistryService = require('../services/registry-service'); const AppHelper = require('../helpers/app-helper'); +const CliDataTypes = require('./cli-data-types'); class Registry extends BaseCLIHandler { constructor() { @@ -69,12 +70,12 @@ class Registry extends BaseCLIHandler { group: [constants.CMD_ADD, constants.CMD_UPDATE] }, { - name: 'user-id', alias: 'u', type: Number, numberType: 'integer', + name: 'user-id', alias: 'u', type: CliDataTypes.Integer, description: 'User\'s id', group: [constants.CMD_ADD] }, { - name: 'item-id', alias: 'i', type: Number, numberType: 'integer', + name: 'item-id', alias: 'i', type: CliDataTypes.Integer, description: 'Item\'s id', group: [constants.CMD_REMOVE, constants.CMD_UPDATE] } diff --git a/src/cli/tunnel.js b/src/cli/tunnel.js index e9ad41649..79501b189 100644 --- a/src/cli/tunnel.js +++ b/src/cli/tunnel.js @@ -20,7 +20,7 @@ const CliDecorator = require('../decorators/cli-decorator'); const Errors = require('../helpers/errors'); const ErrorMessages = require('../helpers/error-messages'); const AppHelper = require('../helpers/app-helper'); - +const CliDataTypes = require('./cli-data-types'); class Tunnel extends BaseCLIHandler { constructor() { @@ -54,7 +54,7 @@ class Tunnel extends BaseCLIHandler { group: [constants.CMD_UPDATE] }, { - name: 'port', alias: 'o', type: Number, numberType: 'integer', + name: 'port', alias: 'o', type: CliDataTypes.Integer, description: 'Tunnel port', group: [constants.CMD_UPDATE] }, diff --git a/src/helpers/app-helper.js b/src/helpers/app-helper.js index e24d9ad3e..1a70210f2 100644 --- a/src/helpers/app-helper.js +++ b/src/helpers/app-helper.js @@ -189,6 +189,28 @@ function trimCertificate(cert) { return result; } +function argsArrayAsMap(args) { + let argsVars = args.join(' ').split(/(?= -{1,2}[^-]+)/); + const argsMap = new Map(); + argsVars + .map(pair => pair.trim()) + .map(pair => { + const spaceIndex = pair.indexOf(' '); + let key, values; + if (spaceIndex !== -1) { + key = pair.substr(0, pair.indexOf(' ')); + values = pair.substr(pair.indexOf(' ')+1).split(' '); + argsMap.set(key, values); + } else { + key = pair; + values = []; + } + argsMap.set(key, values); + + }); + return argsMap; +} + function validateParameters(command, commandDefinitions, args) { // 1st argument = command args.shift(); @@ -196,61 +218,60 @@ function validateParameters(command, commandDefinitions, args) { const possibleAliasesList = _getPossibleAliasesList(command, commandDefinitions); const possibleArgsList = _getPossibleArgsList(command, commandDefinitions); - let currentArgType; + let expectedValueType; let currentArgName; - let numberType; - for (const arg of args) { - // arg is [argument, alias, value] - if (arg.startsWith("--")) { // argument + if (args.length === 0) { + return + } + const argsMap = argsArrayAsMap(args); + + argsMap.forEach((values, key) => { + if (key.startsWith("--")) { // argument // '--ssl-cert' format -> 'ssl-cert' format - const argument = arg.substr(2); + const argument = key.substr(2); _validateArg(argument, possibleArgsList); currentArgName = argument; - currentArgType = _getValType(argument, commandDefinitions); - if (currentArgType === 'number') { - numberType = commandDefinitions.filter(command => command.name === currentArgName)[0].numberType - } - } else if (arg.startsWith("-")) { // alias + expectedValueType = _getValType(argument, commandDefinitions); + } else if (key.startsWith("-")) { // alias // '-q' format -> 'q' format - const alias = arg.substr(1); + const alias = key.substr(1); _validateArg(alias, possibleAliasesList); currentArgName = alias; - currentArgType = _getValType(alias, commandDefinitions); - if (currentArgType === 'number') { - numberType = commandDefinitions.filter(command => command.alias === currentArgName)[0].numberType - } - } else { - // value - let valType; - const nArg = new Number(arg); - if (isNaN(nArg)) { + expectedValueType = _getValType(alias, commandDefinitions); + } + + let valType; + if (values.length === 0) { + valType = 'boolean'; + } else if (values.length === 1) { + const firstVal = Number(values[0]); + if (Number.isNaN(firstVal.valueOf())) { valType = 'string'; - } else if (_isInt(arg)){ + } else if (Number.isInteger(firstVal.valueOf())) { valType = 'integer'; - } else if (_isFloat(arg)){ - valType = 'float'; } else { - valType = 'number'; - } - if (valType !== currentArgType && currentArgType !== 'string' && valType !== numberType) { - if (valType !== 'integer' && numberType !== 'float') { - if (valType !== 'number' && numberType) { - currentArgType = numberType; - } - throw new Errors.InvalidArgumentTypeError(formatMessage(ErrorMessages.INVALID_CLI_ARGUMENT_TYPE, currentArgName, currentArgType)) - } + valType = 'float' } } - } -} - -function _isInt(n){ - return Number(n) % 1 === 0; -} + //TODO else validate multiply parameters. Add after multiply parameters will be used in cli api + + let isValidType = true; + if (expectedValueType === 'string' && valType === 'boolean') { + isValidType = false; + } else if ((expectedValueType === 'float' || expectedValueType === 'number') + && (valType !== 'float' && valType !== 'number' && valType !== 'integer')) { + isValidType = false; + } else if (expectedValueType === 'integer' && valType !== 'integer') { + isValidType = false; + } else if (expectedValueType === 'boolean' && valType !== 'boolean') { + isValidType = false; + } -function _isFloat(n){ - return Number(n) % 1 !== 0; + if (!isValidType) { + throw new Errors.InvalidArgumentTypeError(formatMessage(ErrorMessages.INVALID_CLI_ARGUMENT_TYPE, currentArgName, expectedValueType)); + } + }) } function _validateArg(arg, aliasesList) { diff --git a/src/services/catalog-service.js b/src/services/catalog-service.js index 5252e7764..69aaf578b 100644 --- a/src/services/catalog-service.js +++ b/src/services/catalog-service.js @@ -282,7 +282,7 @@ const _updateCatalogItem = async function (data, where, transaction) { catalogItem = AppHelper.deleteUndefinedFields(catalogItem); if (!catalogItem || AppHelper.isEmpty(catalogItem)) { - throw new Errors.NotFoundError(ErrorMessages.CATALOG_UPDATE_NO_FIELDS); + return } if (data.registryId) { const registry = await RegistryManager.findOne({id: data.registryId}, transaction); @@ -314,7 +314,11 @@ const _updateCatalogItemImages = async function (data, transaction) { await CatalogItemImageManager.updateOrCreate({ catalogItemId: data.id, fogTypeId: image.fogTypeId - }, image, transaction); + }, { + catalogItemId: data.id, + fogTypeId: image.fogTypeId, + containerImage: image.containerImage + }, transaction); } } }; diff --git a/test/src/services/catalog-service.test.js b/test/src/services/catalog-service.test.js index e612e87c7..ed505e6c4 100644 --- a/test/src/services/catalog-service.test.js +++ b/test/src/services/catalog-service.test.js @@ -491,11 +491,10 @@ describe('Catalog Service', () => { }); context('when AppHelper#isEmpty() fails', () => { - const err = new Errors.NotFoundError(ErrorMessages.CATALOG_UPDATE_NO_FIELDS); - def('isEmptyResponse', () => err); + def('isEmptyResponse', () => error); - it(`fails with ${err}`, () => { - return expect($subject).to.be.rejectedWith(ErrorMessages.CATALOG_UPDATE_NO_FIELDS); + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.equal(undefined) }) }); @@ -561,7 +560,11 @@ describe('Catalog Service', () => { expect(CatalogItemImageManager.updateOrCreate).to.have.been.calledWith({ catalogItemId: data.id, fogTypeId: image1.fogTypeId - }, updatedImage1, transaction); + }, { + catalogItemId: data.id, + fogTypeId: image1.fogTypeId, + containerImage: updatedImage1.containerImage + }, transaction); }); context('when CatalogItemImageManager#updateOrCreate() fails', () => { @@ -578,7 +581,11 @@ describe('Catalog Service', () => { expect(CatalogItemImageManager.updateOrCreate).to.have.been.calledWith({ catalogItemId: id, fogTypeId: image2.fogTypeId - }, updatedImage2, transaction); + }, { + catalogItemId: id, + fogTypeId: image2.fogTypeId, + containerImage: updatedImage2.containerImage + }, transaction); }); context('when CatalogItemImageManager#updateOrCreate() fails', () => { From 97f74a47b8feb1ead03ee5187f7220cf7f3e45f6 Mon Sep 17 00:00:00 2001 From: dbusel <10116634+dbusel@users.noreply.github.com> Date: Thu, 7 Feb 2019 15:07:47 +0300 Subject: [PATCH 7/8] fixes for release (#533) * feat(catalog): allow update catalog item image without regular fields (#529) * feat(catalog): allow update catalog item image without regular fields + fix createOrUpdate for catalogItemManager (create didn't work) Closes ENG-622 * feat(catalog): allow update catalog item image without regular fields + fix tests Closes ENG-622 * Maksimchepelev/fetaure cli validation ENG-546 (#530) * feat(cli): add correct validation for cli + args parsing using Mar of + throw error if value for number arg not provided or string was provided: `--number_arg string` or `--number_arg` - validation of number type (integer/float) because there is no info about type in help * feat(cli): add correct validation for cli + float/integer validation +- number -> float/integer in cli help * feat(cli): add correct validation for cli +- correct regexp for parsing cli * feat(cli): add correct validation for cli +- correct Integer and Float types +- fix some problems Closes ENG-621 * Maksimchepelev/bugs (#532) * feat(cli): delete unnecessary output - delete status code and port mapping id output Closes ENG-621 * fix(microservice): add internal port validation in remove port mapping Closes ENG-623 --- src/cli/microservice.js | 3 +-- src/helpers/error-messages.js | 1 + src/services/connector-port-service.js | 3 --- src/services/microservices-service.js | 3 +++ 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cli/microservice.js b/src/cli/microservice.js index 31d7a2fe5..ab21361f3 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -359,8 +359,7 @@ const _createVolumeMapping = async function (obj, user) { const _removePortMapping = async function (obj, user) { try { - const internalPort = parseInt(obj.internalPort); - await MicroserviceService.deletePortMapping(obj.microserviceUuid, internalPort, user, true); + await MicroserviceService.deletePortMapping(obj.microserviceUuid, obj.internalPort, user, true); logger.info('Port mapping has been removed successfully.'); } catch (e) { logger.error(e.message); diff --git a/src/helpers/error-messages.js b/src/helpers/error-messages.js index ad05bc3c1..9caebc8df 100644 --- a/src/helpers/error-messages.js +++ b/src/helpers/error-messages.js @@ -58,6 +58,7 @@ module.exports = { RESTRICTED_PUBLISHER: "You are not allowed to add catalog item as 'Eclipse ioFog' publisher", REQUIRED_FOG_NODE: 'ioFog node is required.', PORT_MAPPING_ALREADY_EXISTS: 'Port mapping already exists', + PORT_MAPPING_INTERNAL_PORT_NOT_PROVIDED: 'Internal port wasn\'t provided', VOLUME_MAPPING_ALREADY_EXISTS: 'Volume mapping already exists', INVALID_CONNECTOR_DOMAIN: 'Invalid connector domain {}', CERT_PROPERTY_REQUIRED: 'Property "certificate" is required if property "requiresCert" is set to true', diff --git a/src/services/connector-port-service.js b/src/services/connector-port-service.js index bf309344f..235adf59e 100644 --- a/src/services/connector-port-service.js +++ b/src/services/connector-port-service.js @@ -89,7 +89,6 @@ async function closePortOnConnector(connector, ports) { let data = qs.stringify({ mappingid: ports.mappingId }); - console.log(data); let port = connector.devMode ? constants.CONNECTOR_HTTP_PORT : constants.CONNECTOR_HTTPS_PORT; @@ -115,7 +114,6 @@ async function closePortOnConnector(connector, ports) { async function _makeRequest(connector, options, data) { return new Promise((resolve, reject) => { let httpreq = (connector.devMode ? http : https).request(options, function (response) { - console.log(response.statusCode); let output = ''; response.setEncoding('utf8'); @@ -134,7 +132,6 @@ async function _makeRequest(connector, options, data) { }); httpreq.on('error', function (err) { - console.log(err); if (err instanceof Error) return reject(new Error(err.message)); else diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index df3f712fd..15f1e5bdf 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -366,6 +366,9 @@ async function deletePortMapping(microserviceUuid, internalPort, user, isCLI, tr ? {uuid: microserviceUuid} : {uuid: microserviceUuid, userId: user.id}; + if (!internalPort) { + throw new Errors.ValidationError(ErrorMessages.PORT_MAPPING_INTERNAL_PORT_NOT_PROVIDED); + } const microservice = await MicroserviceManager.findOne(where, transaction); if (!microservice) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) From 3b309820e524aac17c601ffcb7899fd7ae617656 Mon Sep 17 00:00:00 2001 From: dbusel <10116634+dbusel@users.noreply.github.com> Date: Thu, 7 Feb 2019 21:36:09 +0300 Subject: [PATCH 8/8] hot fix deploy on prod --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2627b924a..8130d029e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,7 +41,8 @@ jobs: "cd /Controller; NODE_ENV=production node src/main.js stop; git checkout $TRAVIS_BRANCH; npm i; npm test; npm run postman_test; NODE_ENV=production node src/main.js start;" - stage: release - #before_install: + before_install: + - sudo apt-get install sshpass #- git clone "https://github.com/$TRAVIS_REPO_SLUG.git" "$TRAVIS_REPO_SLUG"; #- cd "$TRAVIS_REPO_SLUG"; #- git checkout -qf "$TRAVIS_COMMIT";