ic-code 1.5.0__tar.gz → 1.5.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. {ic_code-1.5.0/src/ic_code.egg-info → ic_code-1.5.3}/PKG-INFO +3 -3
  2. {ic_code-1.5.0 → ic_code-1.5.3}/README.md +2 -2
  3. {ic_code-1.5.0 → ic_code-1.5.3}/docs/gcp/README.md +2 -2
  4. {ic_code-1.5.0 → ic_code-1.5.3}/docs/user_guide.md +1 -1
  5. {ic_code-1.5.0 → ic_code-1.5.3}/pyproject.toml +1 -1
  6. {ic_code-1.5.0 → ic_code-1.5.3}/src/common/gcp_utils.py +38 -30
  7. {ic_code-1.5.0 → ic_code-1.5.3}/src/common/log.py +7 -0
  8. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/__init__.py +1 -1
  9. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/compat/common.py +18 -5
  10. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/config/installer.py +8 -8
  11. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/config/migration.py +28 -23
  12. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/config/secrets.py +2 -3
  13. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/core/logging.py +30 -32
  14. ic_code-1.5.3/src/ic/platforms/aws/disk/__init__.py +1 -0
  15. ic_code-1.5.3/src/ic/platforms/aws/disk/info.py +32 -0
  16. ic_code-1.5.3/src/ic/platforms/aws/ebs/__init__.py +1 -0
  17. ic_code-1.5.3/src/ic/platforms/aws/ebs/info.py +528 -0
  18. ic_code-1.5.3/src/ic/platforms/aws/ebs/mock_data.json +90 -0
  19. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/billing/info.py +3 -3
  20. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/compute/info.py +50 -15
  21. ic_code-1.5.3/src/ic/platforms/gcp/disk/__init__.py +1 -0
  22. ic_code-1.5.3/src/ic/platforms/gcp/disk/info.py +566 -0
  23. ic_code-1.5.3/src/ic/platforms/gcp/disk/mock_data.json +96 -0
  24. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/firewall/info.py +219 -20
  25. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/firewall/mock_data.json +7 -1
  26. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/lb/info.py +329 -53
  27. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/lb/mock_data.json +64 -0
  28. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/vpc/info.py +7 -6
  29. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/ssh/__init__.py +2 -1
  30. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/ssh/auto_ssh.py +7 -24
  31. ic_code-1.5.3/src/ic/platforms/ssh/policy.py +61 -0
  32. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/ssh/server_info.py +6 -14
  33. ic_code-1.5.3/src/ic/platforms/tencent/cbs/__init__.py +1 -0
  34. ic_code-1.5.3/src/ic/platforms/tencent/cbs/info.py +556 -0
  35. ic_code-1.5.3/src/ic/platforms/tencent/cbs/mock_data.json +74 -0
  36. ic_code-1.5.3/src/ic/platforms/tencent/disk/__init__.py +1 -0
  37. ic_code-1.5.3/src/ic/platforms/tencent/disk/info.py +32 -0
  38. {ic_code-1.5.0 → ic_code-1.5.3/src/ic_code.egg-info}/PKG-INFO +3 -3
  39. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic_code.egg-info/SOURCES.txt +14 -0
  40. {ic_code-1.5.0 → ic_code-1.5.3}/LICENSE +0 -0
  41. {ic_code-1.5.0 → ic_code-1.5.3}/MANIFEST.in +0 -0
  42. {ic_code-1.5.0 → ic_code-1.5.3}/SECURITY.md +0 -0
  43. {ic_code-1.5.0 → ic_code-1.5.3}/config/default.yaml +0 -0
  44. {ic_code-1.5.0 → ic_code-1.5.3}/docs/README.md +0 -0
  45. {ic_code-1.5.0 → ic_code-1.5.3}/docs/aws/README.md +0 -0
  46. {ic_code-1.5.0 → ic_code-1.5.3}/docs/cloudflare/README.md +0 -0
  47. {ic_code-1.5.0 → ic_code-1.5.3}/docs/installation.md +0 -0
  48. {ic_code-1.5.0 → ic_code-1.5.3}/docs/oci/README.md +0 -0
  49. {ic_code-1.5.0 → ic_code-1.5.3}/docs/release-guide.md +0 -0
  50. {ic_code-1.5.0 → ic_code-1.5.3}/docs/security.md +0 -0
  51. {ic_code-1.5.0 → ic_code-1.5.3}/docs/ssh/README.md +0 -0
  52. {ic_code-1.5.0 → ic_code-1.5.3}/docs/tencent/README.md +0 -0
  53. {ic_code-1.5.0 → ic_code-1.5.3}/docs/troubleshooting.md +0 -0
  54. {ic_code-1.5.0 → ic_code-1.5.3}/requirements.txt +0 -0
  55. {ic_code-1.5.0 → ic_code-1.5.3}/scripts/bump-version.sh +0 -0
  56. {ic_code-1.5.0 → ic_code-1.5.3}/scripts/cf_edge_nsg_make/cf_edge_nsg_make.py +0 -0
  57. {ic_code-1.5.0 → ic_code-1.5.3}/scripts/ci-detect-platforms.py +0 -0
  58. {ic_code-1.5.0 → ic_code-1.5.3}/scripts/ci-generate-matrix.py +0 -0
  59. {ic_code-1.5.0 → ic_code-1.5.3}/scripts/ci-smoke-test.sh +0 -0
  60. {ic_code-1.5.0 → ic_code-1.5.3}/scripts/deploy.sh +0 -0
  61. {ic_code-1.5.0 → ic_code-1.5.3}/scripts/oracle-policy/user_policy.py +0 -0
  62. {ic_code-1.5.0 → ic_code-1.5.3}/setup.cfg +0 -0
  63. {ic_code-1.5.0 → ic_code-1.5.3}/setup.py +0 -0
  64. {ic_code-1.5.0 → ic_code-1.5.3}/src/common/__init__.py +0 -0
  65. {ic_code-1.5.0 → ic_code-1.5.3}/src/common/gather_env.py +0 -0
  66. {ic_code-1.5.0 → ic_code-1.5.3}/src/common/gcp_config_validator.py +0 -0
  67. {ic_code-1.5.0 → ic_code-1.5.3}/src/common/gcp_monitoring.py +0 -0
  68. {ic_code-1.5.0 → ic_code-1.5.3}/src/common/progress_decorator.py +0 -0
  69. {ic_code-1.5.0 → ic_code-1.5.3}/src/common/slack.py +0 -0
  70. {ic_code-1.5.0 → ic_code-1.5.3}/src/common/utils.py +0 -0
  71. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/cli.py +0 -0
  72. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/commands/__init__.py +0 -0
  73. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/commands/config.py +0 -0
  74. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/commands/security.py +0 -0
  75. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/compat/__init__.py +0 -0
  76. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/compat/cli.py +0 -0
  77. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/config/__init__.py +0 -0
  78. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/config/cleanup.py +0 -0
  79. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/config/docs_organizer.py +0 -0
  80. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/config/external.py +0 -0
  81. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/config/manager.py +0 -0
  82. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/config/migration_utils.py +0 -0
  83. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/config/path_manager.py +0 -0
  84. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/config/schema.py +0 -0
  85. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/config/security.py +0 -0
  86. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/core/__init__.py +0 -0
  87. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/core/dependency_validator.py +0 -0
  88. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/core/desc_helper.py +0 -0
  89. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/core/interfaces/__init__.py +0 -0
  90. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/core/interfaces/command.py +0 -0
  91. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/core/interfaces/formatter.py +0 -0
  92. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/core/interfaces/result.py +0 -0
  93. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/core/platform_discovery.py +0 -0
  94. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/core/session.py +0 -0
  95. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/core/silence_logging.py +0 -0
  96. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/__init__.py +0 -0
  97. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/__init__.py +0 -0
  98. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/cloudfront/__init__.py +0 -0
  99. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/cloudfront/info.py +0 -0
  100. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/codepipeline/__init__.py +0 -0
  101. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/codepipeline/build.py +0 -0
  102. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/codepipeline/deploy.py +0 -0
  103. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/ec2/__init__.py +0 -0
  104. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/ec2/desc.py +0 -0
  105. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/ec2/info.py +0 -0
  106. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/ec2/list_tags.py +0 -0
  107. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/ec2/tag_check.py +0 -0
  108. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/ecs/__init__.py +0 -0
  109. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/ecs/info.py +0 -0
  110. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/ecs/service.py +0 -0
  111. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/ecs/task.py +0 -0
  112. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/eks/__init__.py +0 -0
  113. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/eks/addons.py +0 -0
  114. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/eks/fargate.py +0 -0
  115. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/eks/info.py +0 -0
  116. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/eks/nodes.py +0 -0
  117. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/eks/pods.py +0 -0
  118. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/eks/update_config.py +0 -0
  119. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/fargate/__init__.py +0 -0
  120. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/fargate/info.py +0 -0
  121. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/healthdashboard/__init__.py +0 -0
  122. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/healthdashboard/reboot.py +0 -0
  123. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/lb/__init__.py +0 -0
  124. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/lb/desc.py +0 -0
  125. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/lb/info.py +0 -0
  126. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/lb/list_tags.py +0 -0
  127. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/lb/tag_check.py +0 -0
  128. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/msk/__init__.py +0 -0
  129. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/msk/broker.py +0 -0
  130. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/msk/info.py +0 -0
  131. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/nat/__init__.py +0 -0
  132. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/nat/list_tags.py +0 -0
  133. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/nat/tag_check.py +0 -0
  134. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/profile/__init__.py +0 -0
  135. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/profile/info.py +0 -0
  136. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/rds/__init__.py +0 -0
  137. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/rds/info.py +0 -0
  138. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/rds/list_tags.py +0 -0
  139. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/rds/tag_check.py +0 -0
  140. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/s3/__init__.py +0 -0
  141. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/s3/info.py +0 -0
  142. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/s3/list_tags.py +0 -0
  143. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/s3/tag_check.py +0 -0
  144. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/sg/__init__.py +0 -0
  145. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/sg/info.py +0 -0
  146. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/vpc/__init__.py +0 -0
  147. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/vpc/info.py +0 -0
  148. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/vpc/list_tags.py +0 -0
  149. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/vpc/tag_check.py +0 -0
  150. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/vpn/__init__.py +0 -0
  151. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/aws/vpn/info.py +0 -0
  152. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/__init__.py +0 -0
  153. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/account/__init__.py +0 -0
  154. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/account/info.py +0 -0
  155. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/client.py +0 -0
  156. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/dns/__init__.py +0 -0
  157. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/dns/info.py +0 -0
  158. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/dns/list_info.py +0 -0
  159. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/rules/__init__.py +0 -0
  160. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/rules/info.py +0 -0
  161. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/traffic/__init__.py +0 -0
  162. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/traffic/info.py +0 -0
  163. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/waf/__init__.py +0 -0
  164. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/waf/info.py +0 -0
  165. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/zone/__init__.py +0 -0
  166. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/cloudflare/zone/info.py +0 -0
  167. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/__init__.py +0 -0
  168. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/billing/__init__.py +0 -0
  169. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/billing/mock_data.json +0 -0
  170. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/compute/__init__.py +0 -0
  171. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/compute/desc.py +0 -0
  172. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/compute/mock_data.json +0 -0
  173. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/dns/__init__.py +0 -0
  174. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/dns/info.py +0 -0
  175. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/dns/mock_data.json +0 -0
  176. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/firewall/__init__.py +0 -0
  177. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/functions/__init__.py +0 -0
  178. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/functions/info.py +0 -0
  179. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/functions/mock_data.json +0 -0
  180. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/gke/__init__.py +0 -0
  181. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/gke/info.py +0 -0
  182. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/gke/mock_data.json +0 -0
  183. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/lb/__init__.py +0 -0
  184. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/lb/desc.py +0 -0
  185. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/profile/__init__.py +0 -0
  186. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/profile/info.py +0 -0
  187. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/profile/mock_data.json +0 -0
  188. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/project/__init__.py +0 -0
  189. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/project/info.py +0 -0
  190. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/project/mock_data.json +0 -0
  191. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/run/__init__.py +0 -0
  192. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/run/info.py +0 -0
  193. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/run/mock_data.json +0 -0
  194. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/sql/__init__.py +0 -0
  195. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/sql/info.py +0 -0
  196. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/sql/mock_data.json +0 -0
  197. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/storage/__init__.py +0 -0
  198. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/storage/info.py +0 -0
  199. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/storage/mock_data.json +0 -0
  200. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/vpc/__init__.py +0 -0
  201. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/gcp/vpc/mock_data.json +0 -0
  202. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/__init__.py +0 -0
  203. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/common/__init__.py +0 -0
  204. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/common/utils.py +0 -0
  205. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/compartment/__init__.py +0 -0
  206. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/compartment/info.py +0 -0
  207. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/cost/__init__.py +0 -0
  208. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/cost/credit.py +0 -0
  209. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/cost/usage.py +0 -0
  210. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/info/__init__.py +0 -0
  211. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/info/oci_info.py +0 -0
  212. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/lb/__init__.py +0 -0
  213. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/lb/info.py +0 -0
  214. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/nsg/__init__.py +0 -0
  215. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/nsg/info.py +0 -0
  216. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/obj/__init__.py +0 -0
  217. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/obj/info.py +0 -0
  218. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/policy/__init__.py +0 -0
  219. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/policy/info.py +0 -0
  220. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/policy/search.py +0 -0
  221. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/vcn/__init__.py +0 -0
  222. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/vcn/info.py +0 -0
  223. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/vm/__init__.py +0 -0
  224. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/vm/info.py +0 -0
  225. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/volume/__init__.py +0 -0
  226. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/oci/volume/info.py +0 -0
  227. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/ssh/auto/__init__.py +0 -0
  228. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/ssh/auto/scan.py +0 -0
  229. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/ssh/server/__init__.py +0 -0
  230. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/ssh/server/info.py +0 -0
  231. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/__init__.py +0 -0
  232. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/clb/__init__.py +0 -0
  233. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/clb/desc.py +0 -0
  234. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/clb/info.py +0 -0
  235. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/clb/traffic.py +0 -0
  236. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/client.py +0 -0
  237. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/cvm/__init__.py +0 -0
  238. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/cvm/desc.py +0 -0
  239. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/cvm/info.py +0 -0
  240. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/lighthouse/__init__.py +0 -0
  241. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/lighthouse/info.py +0 -0
  242. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/nat/__init__.py +0 -0
  243. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/nat/info.py +0 -0
  244. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/profile/__init__.py +0 -0
  245. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/profile/info.py +0 -0
  246. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/sg/__init__.py +0 -0
  247. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/sg/info.py +0 -0
  248. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/tke/__init__.py +0 -0
  249. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/tke/info.py +0 -0
  250. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/vpc/__init__.py +0 -0
  251. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/platforms/tencent/vpc/info.py +0 -0
  252. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/security/__init__.py +0 -0
  253. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/security/config.py +0 -0
  254. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/security/detector.py +0 -0
  255. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/security/guidance.py +0 -0
  256. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/security/hooks.py +0 -0
  257. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/security/patterns.py +0 -0
  258. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic/security/scanner.py +0 -0
  259. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic_code.egg-info/dependency_links.txt +0 -0
  260. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic_code.egg-info/entry_points.txt +0 -0
  261. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic_code.egg-info/requires.txt +0 -0
  262. {ic_code-1.5.0 → ic_code-1.5.3}/src/ic_code.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ic-code
3
- Version: 1.5.0
3
+ Version: 1.5.3
4
4
  Summary: Infrastructure CLI tool for managing AWS, GCP, OCI, CloudFlare, SSH, and more
5
5
  Home-page: https://github.com/dgr009/ic
6
6
  Author: SangYun Kim
@@ -147,7 +147,7 @@ A comprehensive, production-grade Infrastructure Command Line Interface tool for
147
147
  - **Networking**: VPC, Subnets, NAT Gateways, CLB (Load Balancers - listener rules, health check, target health analysis & network traffic bandwidth statistics), Security Groups (with Ingress/Egress rules & tree view)
148
148
  - **Authentication**: Multi-account STS AssumeRole support, Profile management (`ic tencent profile info` via `~/.tencent/credentials`)
149
149
 
150
- ### 3. 🟩 GCP Services (Production Ready - v1.5.0)
150
+ ### 3. 🟩 GCP Services (Production Ready - v1.5.3)
151
151
  - **Compute Engine**: VM instances with status, zone, machine type (custom parsing), vCPU, memory, disks, IPs, tags, and verbose 15-column output (`ic gcp compute info -v`)
152
152
  - **Compute Detailed Inspection (`desc`)**: Full attribute discovery, dot-notation key filtering (`-k / --keys`), schema discovery (`-l / --list-keys`) for instances
153
153
  - **Load Balancing (LB)**: Forwarding rules, Target proxies, URL maps, Backend services, Health checks, and SSL certificates (`ic gcp lb info`)
@@ -336,7 +336,7 @@ ic tencent tke info
336
336
  ic tencent profile info
337
337
  ```
338
338
 
339
- ### GCP Commands (v1.5.0)
339
+ ### GCP Commands (v1.5.3)
340
340
 
341
341
  ```bash
342
342
  # Compute Engine VM instances (summary & verbose 15-column output)
@@ -41,7 +41,7 @@ A comprehensive, production-grade Infrastructure Command Line Interface tool for
41
41
  - **Networking**: VPC, Subnets, NAT Gateways, CLB (Load Balancers - listener rules, health check, target health analysis & network traffic bandwidth statistics), Security Groups (with Ingress/Egress rules & tree view)
42
42
  - **Authentication**: Multi-account STS AssumeRole support, Profile management (`ic tencent profile info` via `~/.tencent/credentials`)
43
43
 
44
- ### 3. 🟩 GCP Services (Production Ready - v1.5.0)
44
+ ### 3. 🟩 GCP Services (Production Ready - v1.5.3)
45
45
  - **Compute Engine**: VM instances with status, zone, machine type (custom parsing), vCPU, memory, disks, IPs, tags, and verbose 15-column output (`ic gcp compute info -v`)
46
46
  - **Compute Detailed Inspection (`desc`)**: Full attribute discovery, dot-notation key filtering (`-k / --keys`), schema discovery (`-l / --list-keys`) for instances
47
47
  - **Load Balancing (LB)**: Forwarding rules, Target proxies, URL maps, Backend services, Health checks, and SSL certificates (`ic gcp lb info`)
@@ -230,7 +230,7 @@ ic tencent tke info
230
230
  ic tencent profile info
231
231
  ```
232
232
 
233
- ### GCP Commands (v1.5.0)
233
+ ### GCP Commands (v1.5.3)
234
234
 
235
235
  ```bash
236
236
  # Compute Engine VM instances (summary & verbose 15-column output)
@@ -1,6 +1,6 @@
1
1
  # GCP Platform Documentation
2
2
 
3
- This directory contains documentation for the GCP (Google Cloud Platform) integration in IC CLI (v1.5.0).
3
+ This directory contains documentation for the GCP (Google Cloud Platform) integration in IC CLI (v1.5.3).
4
4
 
5
5
  ---
6
6
 
@@ -12,7 +12,7 @@ This directory contains documentation for the GCP (Google Cloud Platform) integr
12
12
 
13
13
  ---
14
14
 
15
- ## Services Supported (v1.5.0)
15
+ ## Services Supported (v1.5.3)
16
16
 
17
17
  | Service | Commands | Key Features |
18
18
  |---|---|---|
@@ -47,7 +47,7 @@ ic config show
47
47
  - **VPC / NAT / TKE**: `ic tencent vpc info` / `ic tencent nat info` / `ic tencent tke info`
48
48
  - **자격 증명 확인**: `ic tencent profile info`
49
49
 
50
- ### 3. 🟩 GCP Services (v1.5.0)
50
+ ### 3. 🟩 GCP Services (v1.5.3)
51
51
  - **Compute Engine (요약 & 15개 컬럼 상세 & desc)**:
52
52
  - `ic gcp compute info`: 기본 요약 목록
53
53
  - `ic gcp compute info -v`: 상세 15열 뷰 (vCPU, Mem, Disks, Net/Subnet, Tags 등)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ic-code"
7
- version = "1.5.0"
7
+ version = "1.5.3"
8
8
  authors = [
9
9
  {name = "sykim", email = "cruiser594@gmail.com"},
10
10
  ]
@@ -13,8 +13,9 @@ from google.cloud.resourcemanager_v3.types import SearchProjectsRequest, GetProj
13
13
  from google.api_core import exceptions as gcp_exceptions
14
14
  from google.api_core import retry
15
15
  from ic.config.manager import ConfigManager
16
+ from common.progress_decorator import ManualProgress
16
17
 
17
- from .log import log_info, log_info_non_console, log_error, log_exception
18
+ from .log import log_info, log_info_non_console, log_error, log_error_file_only, log_exception
18
19
 
19
20
  # Import configuration validator
20
21
  try:
@@ -327,13 +328,13 @@ class GCPProjectManager:
327
328
  return project.state.name == "ACTIVE"
328
329
 
329
330
  except gcp_exceptions.NotFound:
330
- log_error(f"프로젝트를 찾을 수 없음: {project_id}")
331
+ log_info_non_console(f"프로젝트를 찾을 수 없음: {project_id}")
331
332
  return False
332
333
  except gcp_exceptions.PermissionDenied:
333
- log_error(f"프로젝트 접근 권한 없음: {project_id}")
334
+ log_info_non_console(f"프로젝트 접근 권한 없음: {project_id}")
334
335
  return False
335
336
  except Exception as e:
336
- log_error(f"프로젝트 접근 검증 실패: {project_id}, Error={e}")
337
+ log_info_non_console(f"프로젝트 접근 검증 실패: {project_id}, Error={e}")
337
338
  return False
338
339
 
339
340
  def get_project_info(self, project_id: str) -> Optional[Dict[str, Any]]:
@@ -360,7 +361,7 @@ class GCPProjectManager:
360
361
  }
361
362
 
362
363
  except Exception as e:
363
- log_error(f"프로젝트 정보 조회 실패: {project_id}, Error={e}")
364
+ log_info_non_console(f"프로젝트 정보 조회 실패: {project_id}, Error={e}")
364
365
  return None
365
366
 
366
367
 
@@ -377,27 +378,34 @@ class GCPResourceCollector:
377
378
  def parallel_collect(self, projects: List[str], collect_func: Callable, *args, **kwargs) -> List[Any]:
378
379
  """여러 프로젝트에서 병렬로 리소스를 수집합니다."""
379
380
  results = []
381
+ progress_desc = kwargs.pop('progress_desc', None) or f"Collecting GCP resources across {len(projects)} project(s)"
380
382
 
381
- with ThreadPoolExecutor(max_workers=_get_env_int('GCP_MAX_WORKERS', 10)) as executor:
382
- futures = []
383
-
384
- for project_id in projects:
385
- future = executor.submit(
386
- self._safe_collect, collect_func, project_id, *args, **kwargs
387
- )
388
- futures.append((future, project_id))
389
-
390
- for future, project_id in futures:
391
- try:
392
- result = future.result(timeout=_get_env_int('GCP_REQUEST_TIMEOUT', 30))
393
- if result:
394
- if isinstance(result, list):
395
- results.extend(result)
383
+ with ManualProgress(progress_desc, total=len(projects)) as progress:
384
+ with ThreadPoolExecutor(max_workers=_get_env_int('GCP_MAX_WORKERS', 10)) as executor:
385
+ futures = []
386
+
387
+ for project_id in projects:
388
+ future = executor.submit(
389
+ self._safe_collect, collect_func, project_id, *args, **kwargs
390
+ )
391
+ futures.append((future, project_id))
392
+
393
+ for future, project_id in futures:
394
+ try:
395
+ result = future.result(timeout=_get_env_int('GCP_REQUEST_TIMEOUT', 30))
396
+ if result:
397
+ if isinstance(result, list):
398
+ results.extend(result)
399
+ else:
400
+ results.append(result)
401
+ item_count = len(result) if isinstance(result, list) else 1
402
+ progress.update(f"Processed {project_id} ({item_count} items)", advance=1)
396
403
  else:
397
- results.append(result)
398
- except Exception as e:
399
- err_msg = str(e) or type(e).__name__
400
- log_error(f"프로젝트 {project_id}에서 리소스 수집 실패: {err_msg}")
404
+ progress.update(f"Processed {project_id} (0 items)", advance=1)
405
+ except Exception as e:
406
+ err_msg = str(e) or type(e).__name__
407
+ log_info_non_console(f"프로젝트 {project_id}에서 리소스 수집 실패: {err_msg}")
408
+ progress.update(f"Failed {project_id} - {err_msg[:40]}", advance=1)
401
409
 
402
410
  return results
403
411
 
@@ -406,7 +414,7 @@ class GCPResourceCollector:
406
414
  try:
407
415
  return self.handle_api_errors(lambda: collect_func(project_id, *args, **kwargs))
408
416
  except Exception as e:
409
- log_error(f"리소스 수집 중 오류 발생: Project={project_id}, Error={e}")
417
+ log_info_non_console(f"리소스 수집 중 오류 발생: Project={project_id}, Error={e}")
410
418
  return None
411
419
 
412
420
  def handle_api_errors(self, func: Callable) -> Any:
@@ -429,19 +437,19 @@ class GCPResourceCollector:
429
437
  try:
430
438
  return _retry_func()
431
439
  except gcp_exceptions.PermissionDenied as e:
432
- log_error(f"권한 거부: {e}")
440
+ log_info_non_console(f"권한 거부: {e}")
433
441
  raise
434
442
  except gcp_exceptions.NotFound as e:
435
- log_error(f"리소스를 찾을 수 없음: {e}")
443
+ log_info_non_console(f"리소스를 찾을 수 없음: {e}")
436
444
  return None
437
445
  except gcp_exceptions.Forbidden as e:
438
- log_error(f"API가 비활성화되었거나 접근 금지: {e}")
446
+ log_info_non_console(f"API가 비활성화되었거나 접근 금지: {e}")
439
447
  return None
440
448
  except gcp_exceptions.TooManyRequests as e:
441
- log_error(f"API 요청 한도 초과: {e}")
449
+ log_info_non_console(f"API 요청 한도 초과: {e}")
442
450
  raise
443
451
  except Exception as e:
444
- log_error(f"예상치 못한 API 오류: {e}")
452
+ log_info_non_console(f"예상치 못한 API 오류: {e}")
445
453
  raise
446
454
 
447
455
  def apply_filters(self, resources: List[Dict], filters: Dict[str, Any]) -> List[Dict]:
@@ -68,6 +68,13 @@ def log_info(message: str):
68
68
  if os.environ.get("IC_VERBOSE") == "true":
69
69
  console.print(f"[bold cyan]INFO:[/bold cyan] {message}")
70
70
 
71
+ def log_error_file_only(message: str):
72
+ """ERROR 레벨 로그 출력 + 콘솔 미표시 (파일 전용)"""
73
+ if NEW_LOGGING_AVAILABLE and ic_logger:
74
+ ic_logger.log_error_file_only(message)
75
+ else:
76
+ logger.error(message)
77
+
71
78
  def log_error(message: str):
72
79
  """ERROR 레벨 로그 출력 + 콘솔 표시"""
73
80
  if NEW_LOGGING_AVAILABLE and ic_logger:
@@ -4,7 +4,7 @@ IC (Infra Resource Management CLI) - A comprehensive tool for managing cloud inf
4
4
  This package provides CLI tools and libraries for managing AWS, GCP, OCI, CloudFlare, and SSH resources.
5
5
  """
6
6
 
7
- __version__ = "1.5.0"
7
+ __version__ = "1.5.3"
8
8
  __author__ = "SangYun"
9
9
  __email__ = "cruiser594@gmail.com"
10
10
 
@@ -36,6 +36,18 @@ def log_error(message: str, **kwargs) -> None:
36
36
  logger.log_error(message)
37
37
 
38
38
 
39
+ def log_error_file_only(message: str, **kwargs) -> None:
40
+ """
41
+ Backward compatibility function for log_error_file_only.
42
+
43
+ Args:
44
+ message: Error message to log to file
45
+ **kwargs: Additional keyword arguments (ignored for compatibility)
46
+ """
47
+ logger = get_logger()
48
+ logger.log_error_file_only(message)
49
+
50
+
39
51
  def log_env_short(env_dict=None, **kwargs) -> None:
40
52
  """
41
53
  Backward compatibility function for log_env_short.
@@ -72,7 +84,7 @@ def log_args_short(args: Any) -> None:
72
84
  logger.log_args(args)
73
85
 
74
86
 
75
- def gather_env_for_command(platform: str, service: str = None, command: str = None) -> Dict[str, Any]:
87
+ def gather_env_for_command(platform: str, service: Optional[str] = None, command: Optional[str] = None) -> Dict[str, Any]:
76
88
  """
77
89
  Backward compatibility function for gather_env_for_command.
78
90
 
@@ -124,7 +136,7 @@ class GatherEnvCompat:
124
136
  """Compatibility class for common.gather_env module."""
125
137
 
126
138
  @staticmethod
127
- def gather_env_for_command(platform: str, service: str = None, command: str = None) -> Dict[str, Any]:
139
+ def gather_env_for_command(platform: str, service: Optional[str] = None, command: Optional[str] = None) -> Dict[str, Any]:
128
140
  """Gather environment for command."""
129
141
  return gather_env_for_command(platform, service, command)
130
142
 
@@ -135,7 +147,7 @@ gather_env_compat = GatherEnvCompat()
135
147
 
136
148
 
137
149
  # Utility functions for AWS session compatibility
138
- def get_aws_session_compat(account_id: str, region: str = None):
150
+ def get_aws_session_compat(account_id: str, region: Optional[str] = None):
139
151
  """
140
152
  Backward compatibility function for AWS session creation.
141
153
 
@@ -199,8 +211,8 @@ def get_gcp_client_compat(service_type: str):
199
211
 
200
212
  # Import GCP utilities if available
201
213
  try:
202
- from common.gcp_utils import get_gcp_client
203
- return get_gcp_client(service_type)
214
+ from common.gcp_utils import create_gcp_client
215
+ return create_gcp_client(service_type)
204
216
  except ImportError:
205
217
  raise ImportError("GCP utilities not available. Please install google-cloud dependencies.")
206
218
 
@@ -208,6 +220,7 @@ def get_gcp_client_compat(service_type: str):
208
220
  # Export compatibility functions
209
221
  __all__ = [
210
222
  'log_error',
223
+ 'log_error_file_only',
211
224
  'log_env_short',
212
225
  'log_args_short',
213
226
  'gather_env_for_command',
@@ -104,15 +104,15 @@ class ConfigInstaller:
104
104
 
105
105
  def _install_secrets_example(self, target_path: Path) -> None:
106
106
  """Install secrets.yaml.example file."""
107
- secrets_example = self.config_generator.generate_secrets_example()
108
- secrets_file = target_path / 'secrets.yaml.example'
107
+ template_file_content = self.config_generator.generate_secrets_example()
108
+ example_file_path = target_path / 'secrets.yaml.example'
109
109
 
110
- with open(secrets_file, 'w') as f:
111
- f.write(secrets_example)
110
+ with open(example_file_path, 'w') as f:
111
+ f.write(template_file_content)
112
112
 
113
113
  # Set file permissions
114
114
  if os.name != 'nt': # Not Windows
115
- os.chmod(secrets_file, 0o644)
115
+ os.chmod(example_file_path, 0o644)
116
116
 
117
117
 
118
118
  class DefaultConfigGenerator:
@@ -181,7 +181,7 @@ class DefaultConfigGenerator:
181
181
  Returns:
182
182
  Example secrets configuration as YAML string
183
183
  """
184
- secrets_example = {
184
+ template_config = {
185
185
  'aws': {
186
186
  'profile': 'your-aws-profile-name',
187
187
  'access_key_id': 'AKIA...',
@@ -209,9 +209,9 @@ class DefaultConfigGenerator:
209
209
  }
210
210
 
211
211
  # Add comprehensive comments for secrets
212
- yaml_content = self._add_secrets_comments()
212
+ yaml_file_content = self._add_secrets_comments()
213
213
 
214
- return yaml_content
214
+ return yaml_file_content
215
215
 
216
216
  def _add_yaml_comments(self) -> str:
217
217
  """Add comprehensive comments to default YAML configuration."""
@@ -50,9 +50,9 @@ class MigrationManager:
50
50
  # Check if YAML files already exist
51
51
  config_dir = Path("config")
52
52
  default_yaml = config_dir / "default.yaml"
53
- secrets_yaml = config_dir / "secrets.yaml"
53
+ secrets_file_path = config_dir / "secrets.yaml"
54
54
 
55
- if not force and (default_yaml.exists() or secrets_yaml.exists()):
55
+ if not force and (default_yaml.exists() or secrets_file_path.exists()):
56
56
  logger.warning("YAML configuration files already exist. Use force=True to overwrite.")
57
57
  return False
58
58
 
@@ -69,8 +69,8 @@ class MigrationManager:
69
69
  # Backup existing files if they exist
70
70
  if default_yaml.exists():
71
71
  self._backup_file(default_yaml)
72
- if secrets_yaml.exists():
73
- self._backup_file(secrets_yaml)
72
+ if secrets_file_path.exists():
73
+ self._backup_file(secrets_file_path)
74
74
 
75
75
  # Save configurations
76
76
  success = True
@@ -81,11 +81,11 @@ class MigrationManager:
81
81
 
82
82
  # Save secrets configuration
83
83
  if secrets_config:
84
- success &= self._save_yaml_config(secrets_yaml, secrets_config)
84
+ success &= self._save_yaml_config(secrets_file_path, secrets_config)
85
85
 
86
86
  # Set restrictive permissions on secrets file
87
87
  try:
88
- secrets_yaml.chmod(0o600)
88
+ secrets_file_path.chmod(0o600)
89
89
  except Exception as e:
90
90
  logger.warning(f"Failed to set restrictive permissions on secrets file: {e}")
91
91
 
@@ -94,7 +94,7 @@ class MigrationManager:
94
94
  self._backup_file(env_path)
95
95
 
96
96
  # Record migration
97
- self._record_migration(env_path, default_yaml, secrets_yaml)
97
+ self._record_migration(env_path, default_yaml, secrets_file_path)
98
98
 
99
99
  logger.info("Successfully migrated .env file to YAML configuration")
100
100
  return True
@@ -388,11 +388,11 @@ class MigrationManager:
388
388
  yaml.dump(config, f, default_flow_style=False, indent=2,
389
389
  allow_unicode=True, sort_keys=False)
390
390
 
391
- logger.info(f"Saved configuration to {file_path}")
391
+ logger.info("Saved configuration to %s", file_path.name)
392
392
  return True
393
393
 
394
394
  except Exception as e:
395
- logger.error(f"Failed to save configuration to {file_path}: {e}")
395
+ logger.error("Failed to save configuration to %s: %s", file_path.name, e)
396
396
  return False
397
397
 
398
398
  def _backup_file(self, file_path: Path) -> Optional[Path]:
@@ -418,20 +418,20 @@ class MigrationManager:
418
418
 
419
419
  try:
420
420
  shutil.copy2(file_path, backup_path)
421
- logger.info(f"Backed up {file_path} to {backup_path}")
421
+ logger.info("Backed up %s to %s", file_path.name, backup_path.name)
422
422
  return backup_path
423
423
  except Exception as e:
424
- logger.error(f"Failed to backup {file_path}: {e}")
424
+ logger.error("Failed to backup %s: %s", file_path.name, e)
425
425
  return None
426
426
 
427
- def _record_migration(self, env_path: Path, default_yaml: Path, secrets_yaml: Path):
427
+ def _record_migration(self, env_path: Path, default_yaml: Path, secrets_file_path: Path):
428
428
  """Record migration details for history."""
429
429
  migration_record = {
430
430
  "timestamp": datetime.now().isoformat(),
431
431
  "source_file": str(env_path),
432
432
  "target_files": {
433
- "default_config": str(default_yaml),
434
- "secrets_config": str(secrets_yaml) if secrets_yaml.exists() else None
433
+ "default_config_path": str(default_yaml),
434
+ "secrets_config_path": str(secrets_file_path) if secrets_file_path.exists() else None
435
435
  },
436
436
  "backup_location": str(self.backup_dir)
437
437
  }
@@ -446,17 +446,17 @@ class MigrationManager:
446
446
  True if document was created successfully
447
447
  """
448
448
  try:
449
- history_content = self._generate_migration_history_content()
449
+ history_file_content = self._generate_migration_history_content()
450
450
 
451
- history_path = self.backup_dir / "migration_history.md"
452
- with open(history_path, 'w', encoding='utf-8') as f:
453
- f.write(history_content)
451
+ history_file_path = self.backup_dir / "migration_history.md"
452
+ with open(history_file_path, 'w', encoding='utf-8') as f:
453
+ f.write(history_file_content)
454
454
 
455
- logger.info(f"Created migration history document at {history_path}")
455
+ logger.info("Created migration history document at %s", history_file_path.name)
456
456
  return True
457
457
 
458
458
  except Exception as e:
459
- logger.error(f"Failed to create migration history document: {e}")
459
+ logger.error("Failed to create migration history document: %s", e)
460
460
  return False
461
461
 
462
462
  def _generate_migration_history_content(self) -> str:
@@ -507,10 +507,15 @@ backup/
507
507
  content += f"### Migration {i}\n\n"
508
508
  content += f"- **Date**: {record['timestamp']}\n"
509
509
  content += f"- **Source**: {record['source_file']}\n"
510
- content += f"- **Default Config**: {record['target_files']['default_config']}\n"
511
510
 
512
- if record['target_files']['secrets_config']:
513
- content += f"- **Secrets Config**: {record['target_files']['secrets_config']}\n"
511
+ target_files = record.get('target_files', {})
512
+ default_file_path = target_files.get('default_config_path')
513
+ if default_file_path:
514
+ content += f"- **Default Config**: {default_file_path}\n"
515
+
516
+ secrets_file_path = target_files.get('secrets_config_path')
517
+ if secrets_file_path:
518
+ content += f"- **Secrets Config**: {secrets_file_path}\n"
514
519
 
515
520
  content += f"- **Backup Location**: {record['backup_location']}\n\n"
516
521
  else:
@@ -80,11 +80,10 @@ class SecretsManager:
80
80
  secrets = self._merge_secrets(secrets, env_secrets)
81
81
  logger.debug("Merged secrets from environment variables")
82
82
 
83
- # Validate that secrets are properly separated (log to file only)
83
+ # Validate that secrets are properly separated (log summary only, no cleartext secret keys)
84
84
  validation_warnings = self.validate_secrets_separation(secrets)
85
85
  if validation_warnings:
86
- for warning in validation_warnings:
87
- logger.debug(f"Secrets validation: {warning}") # Changed to debug level
86
+ logger.debug("Secrets validation completed with %d checks", len(validation_warnings))
88
87
 
89
88
  self.secrets_data = secrets
90
89
  return secrets
@@ -123,8 +123,10 @@ class ICLogger:
123
123
  console_formatter = logging.Formatter('%(message)s')
124
124
  console_handler.setFormatter(console_formatter)
125
125
 
126
- # Add filter to suppress non-ERROR messages on console
126
+ # Add filter to suppress non-ERROR messages and file-only messages on console
127
127
  def error_only_filter(record):
128
+ if getattr(record, "file_only", False):
129
+ return False
128
130
  return record.levelno >= logging.ERROR
129
131
 
130
132
  console_handler.addFilter(error_only_filter)
@@ -138,7 +140,9 @@ class ICLogger:
138
140
  encoding='utf-8'
139
141
  )
140
142
  file_handler.setLevel(self.file_level)
141
- file_formatter = logging.Formatter(self.log_format)
143
+ file_formatter = logging.Formatter(
144
+ '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
145
+ )
142
146
  file_handler.setFormatter(file_formatter)
143
147
  logger.addHandler(file_handler)
144
148
 
@@ -152,31 +156,27 @@ class ICLogger:
152
156
  # Use security manager to mask sensitive data
153
157
  return self.security_manager.mask_sensitive_in_text(message)
154
158
 
155
- def log_args(self, args: Union[Dict[str, Any], object]) -> None:
159
+ def log_args(self, args: Any) -> None:
156
160
  """
157
- Display command arguments on console and log to file.
161
+ Log command arguments with sensitive data masking.
162
+ Only logs to file, never to console.
158
163
 
159
164
  Args:
160
- args: Arguments dictionary or argparse Namespace object
165
+ args: Command line arguments namespace or dict
161
166
  """
162
- # Convert args to dictionary if it's an object
167
+ if not args:
168
+ return
169
+
170
+ args_dict = {}
163
171
  if hasattr(args, '__dict__'):
164
- args_dict = {k: v for k, v in vars(args).items()
165
- if not k.startswith('_') and k != 'func'}
166
- else:
167
- args_dict = dict(args) if isinstance(args, dict) else {}
168
-
169
- # Format arguments for display
170
- pretty_args = {k: (v if v is not None else "default")
171
- for k, v in args_dict.items()}
172
+ args_dict = {k: v for k, v in vars(args).items() if not k.startswith('_') and k != 'func'}
173
+ elif isinstance(args, dict):
174
+ args_dict = {k: v for k, v in args.items() if not k.startswith('_')}
175
+
176
+ # Format arguments nicely
177
+ pretty_args = {k: (v if v is not None else "default") for k, v in args_dict.items()}
172
178
  args_str = ", ".join(f"{k}={v}" for k, v in pretty_args.items())
173
179
 
174
- # Console output for args (always shown regardless of log level)
175
- if self.console and RICH_AVAILABLE:
176
- self.console.print(f"[bold cyan]Args:[/bold cyan] {args_str}")
177
- else:
178
- print(f"Args: {args_str}")
179
-
180
180
  # File logging with masking
181
181
  masked_args_str = self._mask_message(f"Args: {args_str}")
182
182
  self.logger.info(masked_args_str)
@@ -191,6 +191,16 @@ class ICLogger:
191
191
  masked_message = self._mask_message(message)
192
192
  self.logger.info(masked_message)
193
193
 
194
+ def log_error_file_only(self, message: str) -> None:
195
+ """
196
+ Log ERROR message to file only (not console).
197
+
198
+ Args:
199
+ message: Error message to log to file
200
+ """
201
+ masked_message = self._mask_message(message)
202
+ self.logger.error(masked_message, extra={"file_only": True})
203
+
194
204
  def log_error(self, message: str) -> None:
195
205
  """
196
206
  Log ERROR message to both console and file.
@@ -200,12 +210,6 @@ class ICLogger:
200
210
  """
201
211
  masked_message = self._mask_message(message)
202
212
  self.logger.error(masked_message)
203
-
204
- # Also display on console with Rich formatting if available
205
- if self.console and RICH_AVAILABLE:
206
- self.console.print(f"[bold red]ERROR:[/bold red] {message}")
207
- else:
208
- print(f"ERROR: {message}")
209
213
 
210
214
  def log_critical(self, message: str) -> None:
211
215
  """
@@ -216,12 +220,6 @@ class ICLogger:
216
220
  """
217
221
  masked_message = self._mask_message(message)
218
222
  self.logger.critical(masked_message)
219
-
220
- # Also display on console with Rich formatting if available
221
- if self.console and RICH_AVAILABLE:
222
- self.console.print(f"[bold red]CRITICAL:[/bold red] {message}")
223
- else:
224
- print(f"CRITICAL: {message}")
225
223
 
226
224
  def log_warning(self, message: str) -> None:
227
225
  """
@@ -0,0 +1 @@
1
+ """AWS Disk (EBS alias) module for IC CLI."""
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ AWS Disk Info Command (Alias to AWS EBS Info Command).
4
+ """
5
+
6
+ import argparse
7
+ from typing import Any, Optional
8
+ from ic.platforms.aws.ebs.info import (
9
+ EbsInfoCommand,
10
+ main as ebs_main,
11
+ add_arguments as ebs_add_arguments,
12
+ format_table_output,
13
+ format_tree_output,
14
+ print_paste_format
15
+ )
16
+
17
+
18
+ class AwsDiskInfoCommand(EbsInfoCommand):
19
+ """AWS Disk (EBS) 볼륨 정보 조회 커맨드 (Alias)"""
20
+ pass
21
+
22
+
23
+ def main(args: Optional[argparse.Namespace] = None, config: Any = None) -> None:
24
+ ebs_main(args, config)
25
+
26
+
27
+ def add_arguments(parser: argparse.ArgumentParser) -> None:
28
+ ebs_add_arguments(parser)
29
+
30
+
31
+ if __name__ == "__main__":
32
+ main()
@@ -0,0 +1 @@
1
+ """AWS EBS (Elastic Block Store) module for IC CLI."""