catocli 2.0.4__py3-none-any.whl → 2.0.5__py3-none-any.whl

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.

Potentially problematic release.


This version of catocli might be problematic. Click here for more details.

Files changed (290) hide show
  1. build/lib/catocli/Utils/clidriver.py +268 -0
  2. build/lib/catocli/Utils/profile_manager.py +188 -0
  3. build/lib/catocli/Utils/version_checker.py +192 -0
  4. build/lib/catocli/__init__.py +2 -0
  5. build/lib/catocli/__main__.py +12 -0
  6. build/lib/catocli/parsers/configure/__init__.py +115 -0
  7. build/lib/catocli/parsers/configure/configure.py +307 -0
  8. build/lib/catocli/parsers/custom/__init__.py +57 -0
  9. build/lib/catocli/parsers/custom/customLib.py +561 -0
  10. build/lib/catocli/parsers/custom/export_rules/__init__.py +42 -0
  11. build/lib/catocli/parsers/custom/export_rules/export_rules.py +234 -0
  12. build/lib/catocli/parsers/custom/export_sites/__init__.py +21 -0
  13. build/lib/catocli/parsers/custom/export_sites/export_sites.py +372 -0
  14. build/lib/catocli/parsers/custom/import_rules_to_tf/__init__.py +58 -0
  15. build/lib/catocli/parsers/custom/import_rules_to_tf/import_rules_to_tf.py +451 -0
  16. build/lib/catocli/parsers/custom/import_sites_to_tf/__init__.py +45 -0
  17. build/lib/catocli/parsers/custom/import_sites_to_tf/import_sites_to_tf.py +891 -0
  18. build/lib/catocli/parsers/mutation_accountManagement/__init__.py +48 -0
  19. build/lib/catocli/parsers/mutation_admin/__init__.py +48 -0
  20. build/lib/catocli/parsers/mutation_container/__init__.py +138 -0
  21. build/lib/catocli/parsers/mutation_hardware/__init__.py +22 -0
  22. build/lib/catocli/parsers/mutation_policy/__init__.py +1305 -0
  23. build/lib/catocli/parsers/mutation_sandbox/__init__.py +35 -0
  24. build/lib/catocli/parsers/mutation_site/__init__.py +373 -0
  25. build/lib/catocli/parsers/mutation_sites/__init__.py +373 -0
  26. build/lib/catocli/parsers/mutation_xdr/__init__.py +48 -0
  27. build/lib/catocli/parsers/parserApiClient.py +513 -0
  28. build/lib/catocli/parsers/query_accountBySubdomain/__init__.py +16 -0
  29. build/lib/catocli/parsers/query_accountManagement/__init__.py +16 -0
  30. build/lib/catocli/parsers/query_accountMetrics/__init__.py +16 -0
  31. build/lib/catocli/parsers/query_accountRoles/__init__.py +16 -0
  32. build/lib/catocli/parsers/query_accountSnapshot/__init__.py +16 -0
  33. build/lib/catocli/parsers/query_admin/__init__.py +16 -0
  34. build/lib/catocli/parsers/query_admins/__init__.py +16 -0
  35. build/lib/catocli/parsers/query_appStats/__init__.py +16 -0
  36. build/lib/catocli/parsers/query_appStatsTimeSeries/__init__.py +16 -0
  37. build/lib/catocli/parsers/query_auditFeed/__init__.py +16 -0
  38. build/lib/catocli/parsers/query_catalogs/__init__.py +16 -0
  39. build/lib/catocli/parsers/query_container/__init__.py +16 -0
  40. build/lib/catocli/parsers/query_devices/__init__.py +16 -0
  41. build/lib/catocli/parsers/query_entityLookup/__init__.py +16 -0
  42. build/lib/catocli/parsers/query_events/__init__.py +16 -0
  43. build/lib/catocli/parsers/query_eventsFeed/__init__.py +16 -0
  44. build/lib/catocli/parsers/query_eventsTimeSeries/__init__.py +16 -0
  45. build/lib/catocli/parsers/query_hardware/__init__.py +16 -0
  46. build/lib/catocli/parsers/query_hardwareManagement/__init__.py +16 -0
  47. build/lib/catocli/parsers/query_licensing/__init__.py +16 -0
  48. build/lib/catocli/parsers/query_policy/__init__.py +161 -0
  49. build/lib/catocli/parsers/query_sandbox/__init__.py +16 -0
  50. build/lib/catocli/parsers/query_site/__init__.py +100 -0
  51. build/lib/catocli/parsers/query_siteLocation/__init__.py +13 -0
  52. build/lib/catocli/parsers/query_subDomains/__init__.py +16 -0
  53. build/lib/catocli/parsers/query_xdr/__init__.py +35 -0
  54. build/lib/catocli/parsers/raw/__init__.py +12 -0
  55. build/lib/graphql_client/__init__.py +11 -0
  56. build/lib/graphql_client/api/__init__.py +3 -0
  57. build/lib/graphql_client/api/call_api.py +84 -0
  58. build/lib/graphql_client/api_client.py +192 -0
  59. build/lib/graphql_client/api_client_types.py +409 -0
  60. build/lib/graphql_client/configuration.py +232 -0
  61. build/lib/graphql_client/models/__init__.py +13 -0
  62. build/lib/graphql_client/models/no_schema.py +71 -0
  63. build/lib/schema/catolib.py +1141 -0
  64. build/lib/schema/importSchema.py +60 -0
  65. build/lib/schema/remove_policyid.py +89 -0
  66. build/lib/schema/remove_policyid_mutations.py +89 -0
  67. build/lib/scripts/catolib.py +62 -0
  68. build/lib/scripts/export_if_rules_to_json.py +188 -0
  69. build/lib/scripts/export_wf_rules_to_json.py +111 -0
  70. build/lib/scripts/import_wf_rules_to_tfstate.py +331 -0
  71. build/lib/vendor/certifi/__init__.py +4 -0
  72. build/lib/vendor/certifi/__main__.py +12 -0
  73. build/lib/vendor/certifi/core.py +114 -0
  74. build/lib/vendor/certifi/py.typed +0 -0
  75. build/lib/vendor/six.py +998 -0
  76. build/lib/vendor/urllib3/__init__.py +211 -0
  77. build/lib/vendor/urllib3/_base_connection.py +172 -0
  78. build/lib/vendor/urllib3/_collections.py +483 -0
  79. build/lib/vendor/urllib3/_request_methods.py +278 -0
  80. build/lib/vendor/urllib3/_version.py +16 -0
  81. build/lib/vendor/urllib3/connection.py +1033 -0
  82. build/lib/vendor/urllib3/connectionpool.py +1182 -0
  83. build/lib/vendor/urllib3/contrib/__init__.py +0 -0
  84. build/lib/vendor/urllib3/contrib/emscripten/__init__.py +18 -0
  85. build/lib/vendor/urllib3/contrib/emscripten/connection.py +254 -0
  86. build/lib/vendor/urllib3/contrib/emscripten/fetch.py +418 -0
  87. build/lib/vendor/urllib3/contrib/emscripten/request.py +22 -0
  88. build/lib/vendor/urllib3/contrib/emscripten/response.py +285 -0
  89. build/lib/vendor/urllib3/contrib/pyopenssl.py +552 -0
  90. build/lib/vendor/urllib3/contrib/socks.py +228 -0
  91. build/lib/vendor/urllib3/exceptions.py +321 -0
  92. build/lib/vendor/urllib3/fields.py +341 -0
  93. build/lib/vendor/urllib3/filepost.py +89 -0
  94. build/lib/vendor/urllib3/http2/__init__.py +53 -0
  95. build/lib/vendor/urllib3/http2/connection.py +356 -0
  96. build/lib/vendor/urllib3/http2/probe.py +87 -0
  97. build/lib/vendor/urllib3/poolmanager.py +637 -0
  98. build/lib/vendor/urllib3/py.typed +2 -0
  99. build/lib/vendor/urllib3/response.py +1265 -0
  100. build/lib/vendor/urllib3/util/__init__.py +42 -0
  101. build/lib/vendor/urllib3/util/connection.py +137 -0
  102. build/lib/vendor/urllib3/util/proxy.py +43 -0
  103. build/lib/vendor/urllib3/util/request.py +256 -0
  104. build/lib/vendor/urllib3/util/response.py +101 -0
  105. build/lib/vendor/urllib3/util/retry.py +533 -0
  106. build/lib/vendor/urllib3/util/ssl_.py +513 -0
  107. build/lib/vendor/urllib3/util/ssl_match_hostname.py +159 -0
  108. build/lib/vendor/urllib3/util/ssltransport.py +276 -0
  109. build/lib/vendor/urllib3/util/timeout.py +275 -0
  110. build/lib/vendor/urllib3/util/url.py +471 -0
  111. build/lib/vendor/urllib3/util/util.py +42 -0
  112. build/lib/vendor/urllib3/util/wait.py +124 -0
  113. catocli/Utils/clidriver.py +1 -4
  114. catocli/__init__.py +1 -1
  115. catocli/parsers/custom/export_sites/export_sites.py +2 -2
  116. catocli/parsers/mutation_container/__init__.py +116 -0
  117. catocli/parsers/mutation_container_fqdn/README.md +7 -0
  118. catocli/parsers/mutation_container_fqdn_addValues/README.md +17 -0
  119. catocli/parsers/mutation_container_fqdn_createFromFile/README.md +17 -0
  120. catocli/parsers/mutation_container_fqdn_removeValues/README.md +17 -0
  121. catocli/parsers/mutation_container_fqdn_updateFromFile/README.md +17 -0
  122. catocli/parsers/mutation_container_ipAddressRange/README.md +7 -0
  123. catocli/parsers/mutation_container_ipAddressRange_addValues/README.md +17 -0
  124. catocli/parsers/mutation_container_ipAddressRange_createFromFile/README.md +17 -0
  125. catocli/parsers/mutation_container_ipAddressRange_removeValues/README.md +17 -0
  126. catocli/parsers/mutation_container_ipAddressRange_updateFromFile/README.md +17 -0
  127. catocli/parsers/mutation_policy_internetFirewall_addRule/README.md +1 -1
  128. catocli/parsers/mutation_policy_internetFirewall_updateRule/README.md +1 -1
  129. catocli/parsers/mutation_policy_wanFirewall_addRule/README.md +1 -1
  130. catocli/parsers/mutation_policy_wanFirewall_updateRule/README.md +1 -1
  131. catocli/parsers/parserApiClient.py +25 -11
  132. catocli/parsers/query_policy/README.md +0 -17
  133. catocli/parsers/query_policy/__init__.py +153 -8
  134. catocli/parsers/query_policy_appTenantRestriction/README.md +7 -0
  135. catocli/parsers/query_policy_appTenantRestriction_policy/README.md +17 -0
  136. catocli/parsers/query_policy_dynamicIpAllocation/README.md +7 -0
  137. catocli/parsers/query_policy_dynamicIpAllocation_policy/README.md +17 -0
  138. catocli/parsers/query_policy_internetFirewall/README.md +7 -0
  139. catocli/parsers/query_policy_internetFirewall_policy/README.md +17 -0
  140. catocli/parsers/query_policy_remotePortFwd/README.md +7 -0
  141. catocli/parsers/query_policy_remotePortFwd_policy/README.md +17 -0
  142. catocli/parsers/query_policy_socketLan/README.md +7 -0
  143. catocli/parsers/query_policy_socketLan_policy/README.md +17 -0
  144. catocli/parsers/query_policy_terminalServer/README.md +7 -0
  145. catocli/parsers/query_policy_terminalServer_policy/README.md +17 -0
  146. catocli/parsers/query_policy_wanFirewall/README.md +7 -0
  147. catocli/parsers/query_policy_wanFirewall_policy/README.md +17 -0
  148. catocli/parsers/query_policy_wanNetwork/README.md +7 -0
  149. catocli/parsers/query_policy_wanNetwork_policy/README.md +17 -0
  150. catocli/parsers/query_site/README.md +0 -16
  151. catocli/parsers/query_site/__init__.py +92 -8
  152. catocli/parsers/query_site_availableVersionList/README.md +17 -0
  153. catocli/parsers/query_site_bgpPeer/README.md +17 -0
  154. catocli/parsers/query_site_bgpPeerList/README.md +17 -0
  155. catocli/parsers/query_site_cloudInterconnectConnectionConnectivity/README.md +17 -0
  156. catocli/parsers/query_site_cloudInterconnectPhysicalConnection/README.md +17 -0
  157. catocli/parsers/query_site_cloudInterconnectPhysicalConnectionId/README.md +17 -0
  158. catocli/parsers/query_site_siteBgpStatus/README.md +17 -0
  159. catocli/parsers/raw/README.md +0 -14
  160. catocli/parsers/raw/__init__.py +0 -2
  161. {catocli-2.0.4.dist-info → catocli-2.0.5.dist-info}/METADATA +1 -1
  162. {catocli-2.0.4.dist-info → catocli-2.0.5.dist-info}/RECORD +290 -120
  163. {catocli-2.0.4.dist-info → catocli-2.0.5.dist-info}/top_level.txt +1 -0
  164. graphql_client/api/call_api.py +4 -3
  165. models/mutation.container.fqdn.addValues.json +866 -0
  166. models/mutation.container.fqdn.createFromFile.json +819 -0
  167. models/mutation.container.fqdn.removeValues.json +866 -0
  168. models/mutation.container.fqdn.updateFromFile.json +1045 -0
  169. models/mutation.container.ipAddressRange.addValues.json +1020 -0
  170. models/mutation.container.ipAddressRange.createFromFile.json +819 -0
  171. models/mutation.container.ipAddressRange.removeValues.json +1020 -0
  172. models/mutation.container.ipAddressRange.updateFromFile.json +1045 -0
  173. models/mutation.policy.appTenantRestriction.addRule.json +8 -8
  174. models/mutation.policy.appTenantRestriction.addSection.json +1 -1
  175. models/mutation.policy.appTenantRestriction.createPolicyRevision.json +2 -2
  176. models/mutation.policy.appTenantRestriction.discardPolicyRevision.json +2 -2
  177. models/mutation.policy.appTenantRestriction.moveRule.json +2 -2
  178. models/mutation.policy.appTenantRestriction.moveSection.json +1 -1
  179. models/mutation.policy.appTenantRestriction.publishPolicyRevision.json +2 -2
  180. models/mutation.policy.appTenantRestriction.removeRule.json +2 -2
  181. models/mutation.policy.appTenantRestriction.removeSection.json +1 -1
  182. models/mutation.policy.appTenantRestriction.updatePolicy.json +2 -2
  183. models/mutation.policy.appTenantRestriction.updateRule.json +8 -8
  184. models/mutation.policy.appTenantRestriction.updateSection.json +1 -1
  185. models/mutation.policy.dynamicIpAllocation.addRule.json +1 -1
  186. models/mutation.policy.dynamicIpAllocation.addSection.json +1 -1
  187. models/mutation.policy.dynamicIpAllocation.createPolicyRevision.json +1 -1
  188. models/mutation.policy.dynamicIpAllocation.discardPolicyRevision.json +1 -1
  189. models/mutation.policy.dynamicIpAllocation.moveRule.json +1 -1
  190. models/mutation.policy.dynamicIpAllocation.moveSection.json +1 -1
  191. models/mutation.policy.dynamicIpAllocation.publishPolicyRevision.json +1 -1
  192. models/mutation.policy.dynamicIpAllocation.removeRule.json +1 -1
  193. models/mutation.policy.dynamicIpAllocation.removeSection.json +1 -1
  194. models/mutation.policy.dynamicIpAllocation.updatePolicy.json +1 -1
  195. models/mutation.policy.dynamicIpAllocation.updateRule.json +1 -1
  196. models/mutation.policy.dynamicIpAllocation.updateSection.json +1 -1
  197. models/mutation.policy.internetFirewall.addRule.json +502 -55
  198. models/mutation.policy.internetFirewall.addSection.json +1 -1
  199. models/mutation.policy.internetFirewall.createPolicyRevision.json +127 -10
  200. models/mutation.policy.internetFirewall.discardPolicyRevision.json +127 -10
  201. models/mutation.policy.internetFirewall.moveRule.json +127 -10
  202. models/mutation.policy.internetFirewall.moveSection.json +1 -1
  203. models/mutation.policy.internetFirewall.publishPolicyRevision.json +127 -10
  204. models/mutation.policy.internetFirewall.removeRule.json +127 -10
  205. models/mutation.policy.internetFirewall.removeSection.json +1 -1
  206. models/mutation.policy.internetFirewall.updatePolicy.json +127 -10
  207. models/mutation.policy.internetFirewall.updateRule.json +493 -55
  208. models/mutation.policy.internetFirewall.updateSection.json +1 -1
  209. models/mutation.policy.remotePortFwd.addRule.json +5 -5
  210. models/mutation.policy.remotePortFwd.addSection.json +1 -1
  211. models/mutation.policy.remotePortFwd.createPolicyRevision.json +2 -2
  212. models/mutation.policy.remotePortFwd.discardPolicyRevision.json +2 -2
  213. models/mutation.policy.remotePortFwd.moveRule.json +2 -2
  214. models/mutation.policy.remotePortFwd.moveSection.json +1 -1
  215. models/mutation.policy.remotePortFwd.publishPolicyRevision.json +2 -2
  216. models/mutation.policy.remotePortFwd.removeRule.json +2 -2
  217. models/mutation.policy.remotePortFwd.removeSection.json +1 -1
  218. models/mutation.policy.remotePortFwd.updatePolicy.json +2 -2
  219. models/mutation.policy.remotePortFwd.updateRule.json +5 -5
  220. models/mutation.policy.remotePortFwd.updateSection.json +1 -1
  221. models/mutation.policy.socketLan.addRule.json +16 -16
  222. models/mutation.policy.socketLan.addSection.json +1 -1
  223. models/mutation.policy.socketLan.createPolicyRevision.json +4 -4
  224. models/mutation.policy.socketLan.discardPolicyRevision.json +4 -4
  225. models/mutation.policy.socketLan.moveRule.json +4 -4
  226. models/mutation.policy.socketLan.moveSection.json +1 -1
  227. models/mutation.policy.socketLan.publishPolicyRevision.json +4 -4
  228. models/mutation.policy.socketLan.removeRule.json +4 -4
  229. models/mutation.policy.socketLan.removeSection.json +1 -1
  230. models/mutation.policy.socketLan.updatePolicy.json +4 -4
  231. models/mutation.policy.socketLan.updateRule.json +16 -16
  232. models/mutation.policy.socketLan.updateSection.json +1 -1
  233. models/mutation.policy.terminalServer.addRule.json +1 -1
  234. models/mutation.policy.terminalServer.addSection.json +1 -1
  235. models/mutation.policy.terminalServer.createPolicyRevision.json +1 -1
  236. models/mutation.policy.terminalServer.discardPolicyRevision.json +1 -1
  237. models/mutation.policy.terminalServer.moveRule.json +1 -1
  238. models/mutation.policy.terminalServer.moveSection.json +1 -1
  239. models/mutation.policy.terminalServer.publishPolicyRevision.json +1 -1
  240. models/mutation.policy.terminalServer.removeRule.json +1 -1
  241. models/mutation.policy.terminalServer.removeSection.json +1 -1
  242. models/mutation.policy.terminalServer.updatePolicy.json +1 -1
  243. models/mutation.policy.terminalServer.updateRule.json +1 -1
  244. models/mutation.policy.terminalServer.updateSection.json +1 -1
  245. models/mutation.policy.wanFirewall.addRule.json +500 -53
  246. models/mutation.policy.wanFirewall.addSection.json +1 -1
  247. models/mutation.policy.wanFirewall.createPolicyRevision.json +128 -11
  248. models/mutation.policy.wanFirewall.discardPolicyRevision.json +128 -11
  249. models/mutation.policy.wanFirewall.moveRule.json +128 -11
  250. models/mutation.policy.wanFirewall.moveSection.json +1 -1
  251. models/mutation.policy.wanFirewall.publishPolicyRevision.json +128 -11
  252. models/mutation.policy.wanFirewall.removeRule.json +128 -11
  253. models/mutation.policy.wanFirewall.removeSection.json +1 -1
  254. models/mutation.policy.wanFirewall.updatePolicy.json +128 -11
  255. models/mutation.policy.wanFirewall.updateRule.json +491 -53
  256. models/mutation.policy.wanFirewall.updateSection.json +1 -1
  257. models/mutation.policy.wanNetwork.addRule.json +13 -13
  258. models/mutation.policy.wanNetwork.addSection.json +1 -1
  259. models/mutation.policy.wanNetwork.createPolicyRevision.json +1 -1
  260. models/mutation.policy.wanNetwork.discardPolicyRevision.json +1 -1
  261. models/mutation.policy.wanNetwork.moveRule.json +1 -1
  262. models/mutation.policy.wanNetwork.moveSection.json +1 -1
  263. models/mutation.policy.wanNetwork.publishPolicyRevision.json +1 -1
  264. models/mutation.policy.wanNetwork.removeRule.json +1 -1
  265. models/mutation.policy.wanNetwork.removeSection.json +1 -1
  266. models/mutation.policy.wanNetwork.updatePolicy.json +1 -1
  267. models/mutation.policy.wanNetwork.updateRule.json +13 -13
  268. models/mutation.policy.wanNetwork.updateSection.json +1 -1
  269. models/query.policy.appTenantRestriction.policy.json +3086 -0
  270. models/query.policy.dynamicIpAllocation.policy.json +1934 -0
  271. models/query.policy.internetFirewall.policy.json +7833 -0
  272. models/query.policy.json +233 -0
  273. models/query.policy.remotePortFwd.policy.json +2387 -0
  274. models/query.policy.socketLan.policy.json +7140 -0
  275. models/query.policy.terminalServer.policy.json +1632 -0
  276. models/query.policy.wanFirewall.policy.json +9212 -0
  277. models/query.policy.wanNetwork.policy.json +8010 -0
  278. models/query.site.availableVersionList.json +365 -0
  279. models/query.site.bgpPeer.json +1917 -0
  280. models/query.site.bgpPeerList.json +2076 -0
  281. models/query.site.cloudInterconnectConnectionConnectivity.json +298 -0
  282. models/query.site.cloudInterconnectPhysicalConnection.json +728 -0
  283. models/query.site.cloudInterconnectPhysicalConnectionId.json +660 -0
  284. models/query.site.siteBgpStatus.json +869 -0
  285. schema/catolib.py +13 -6
  286. schema/remove_policyid.py +89 -0
  287. schema/remove_policyid_mutations.py +89 -0
  288. {catocli-2.0.4.dist-info → catocli-2.0.5.dist-info}/LICENSE +0 -0
  289. {catocli-2.0.4.dist-info → catocli-2.0.5.dist-info}/WHEEL +0 -0
  290. {catocli-2.0.4.dist-info → catocli-2.0.5.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,561 @@
1
+ import os
2
+ import json
3
+ import subprocess
4
+ import glob
5
+ from pathlib import Path
6
+ from graphql_client.api.call_api import ApiClient, CallApi
7
+ from graphql_client.api_client import ApiException
8
+ import logging
9
+ from ..parserApiClient import validateArgs
10
+
11
+ def entityTypeList(args, configuration):
12
+ params = vars(args)
13
+ operation = {
14
+ "operationArgs": {
15
+ "accountID": {
16
+ "name": "accountID",
17
+ "required": True,
18
+ }
19
+ }
20
+ }
21
+ variablesObj = { "accountID": (params.get("accountID") if params.get("accountID") else params.get("accountId"))}
22
+
23
+ # Create the API client instance
24
+ api_client = ApiClient(configuration)
25
+
26
+ # Show masked API key in verbose mode (without affecting actual API calls)
27
+ if hasattr(args, 'verbose') and args.verbose and 'x-api-key' in api_client.configuration.api_key:
28
+ print(f"API Key (masked): ***MASKED***")
29
+
30
+ # Create the API instance
31
+ instance = CallApi(api_client)
32
+ operationName = params["operation_name"]
33
+ query = '''query entityLookup ( $type:EntityType! $accountID:ID! $search:String ) {
34
+ entityLookup ( accountID:$accountID type:$type search:$search ) {
35
+ '''+params["operation_name"]+'''s: items {
36
+ description
37
+ '''+params["operation_name"]+''': entity {
38
+ id
39
+ name
40
+ type
41
+ }
42
+ }
43
+ }
44
+ }'''
45
+ body = {
46
+ "query": query,
47
+ "operationName": "entityLookup",
48
+ "variables": {
49
+ "accountID": configuration.accountID,
50
+ "type": params["operation_name"],
51
+ "search": (params.get("s") if params.get("s")!=None else "")
52
+ }
53
+ }
54
+
55
+ isOk, invalidVars, message = validateArgs(variablesObj,operation)
56
+ if isOk==True:
57
+ if params["t"]==True:
58
+ if params["p"]==True:
59
+ print(json.dumps(body,indent=2,sort_keys=True).replace("\\n", "\n").replace("\\t", " "))
60
+ else:
61
+ print(json.dumps(body).replace("\\n", " ").replace("\\t", " ").replace(" "," ").replace(" "," "))
62
+ return None
63
+ else:
64
+ try:
65
+ response = instance.call_api(body,params)
66
+ if params["v"]==True:
67
+ print(json.dumps(response[0]))
68
+ elif params["f"]=="json":
69
+ if params["p"]==True:
70
+ print(json.dumps(response[0].get("data").get("entityLookup").get(params["operation_name"]+"s"),indent=2,sort_keys=True).replace("\\n", "\n").replace("\\t", " "))
71
+ else:
72
+ print(json.dumps(response[0].get("data").get("entityLookup").get(params["operation_name"]+"s")))
73
+ else:
74
+ if len(response[0].get("data").get("entityLookup").get(params["operation_name"]+"s"))==0:
75
+ print("No results found")
76
+ else:
77
+ print("id,name,type,description")
78
+ for site in response[0].get("data").get("entityLookup").get(params["operation_name"]+"s"):
79
+ print(site.get(params["operation_name"]).get('id')+","+site.get(params["operation_name"]).get('name')+","+site.get(params["operation_name"]).get('type')+","+site.get('description'))
80
+ except ApiException as e:
81
+ return e
82
+ else:
83
+ print("ERROR: "+message,", ".join(invalidVars))
84
+
85
+
86
+ # def getEntityLookup(args, configuration, account_id, entity_type, indexIdName=None):
87
+ # """
88
+ # Get entity lookup data from the API and return entities indexed by entityID or custom ID from helperFields
89
+
90
+ # Args:
91
+ # args: Command line arguments containing verbose and other options
92
+ # configuration: API configuration object
93
+ # account_id: The account ID to use for the lookup
94
+ # entity_type: The type of entity to lookup (e.g., "site", "vpnUser", "host", etc.)
95
+ # indexIdName: Optional name of the ID attribute in helperFields to use for indexing instead of entity.id
96
+
97
+ # Returns:
98
+ # dict: A dictionary with entity IDs (or custom IDs) as keys and entity information as values
99
+ # Format: {"entityID1": {"id": "entityID1", "name": "entityName", "type": "entityType", "description": "desc", "indexId": "customID"}, ...}
100
+ # """
101
+ # # Define the entity lookup query
102
+ # entity_query = {
103
+ # "query": "query entityLookup ( $accountID:ID! $type:EntityType! $sortInput:[SortInput] $lookupFilterInput:[LookupFilterInput] ) { entityLookup ( accountID:$accountID type:$type sort:$sortInput filters:$lookupFilterInput ) { items { entity { id name type } description helperFields } total } }",
104
+ # "variables": {
105
+ # "accountID": account_id,
106
+ # "type": entity_type
107
+ # },
108
+ # "operationName": "entityLookup"
109
+ # }
110
+
111
+ # # Create API client instance with params
112
+ # # Create the API client instance
113
+ # entity_api_client = ApiClient(configuration)
114
+
115
+ # # Show masked API key in verbose mode (without affecting actual API calls)
116
+ # if hasattr(args, 'verbose') and args.verbose and 'x-api-key' in entity_api_client.configuration.api_key:
117
+ # print(f"Entity Lookup API Key (masked): ***MASKED***")
118
+
119
+ # # Create the API instance
120
+ # entity_query_instance = CallApi(entity_api_client)
121
+ # params = {
122
+ # 'v': hasattr(args, 'verbose') and args.verbose, # verbose mode
123
+ # 'f': 'json', # format
124
+ # 'p': False, # pretty print
125
+ # 't': False # test mode
126
+ # }
127
+
128
+ # try:
129
+ # # Call the entity lookup API
130
+ # entity_response = entity_query_instance.call_api(entity_query, params)
131
+ # entity_data = entity_response[0] if entity_response else {}
132
+
133
+ # # Show raw API response in verbose mode
134
+ # if hasattr(args, 'verbose') and args.verbose:
135
+ # print("\n" + "=" * 80)
136
+ # print(f"{entity_type.upper()} LOOKUP API RESPONSE:")
137
+ # print("=" * 80)
138
+ # print(json.dumps(entity_data, indent=2))
139
+ # print("=" * 80 + "\n")
140
+
141
+ # # Check for GraphQL errors in entity response
142
+ # if 'errors' in entity_data:
143
+ # error_messages = [error.get('message', 'Unknown error') for error in entity_data['errors']]
144
+ # raise Exception(f"{entity_type} lookup API returned errors: {', '.join(error_messages)}")
145
+
146
+ # if not entity_data or 'data' not in entity_data:
147
+ # raise ValueError(f"Failed to retrieve {entity_type} data from API")
148
+
149
+ # # Extract entity data and create indexed structure
150
+ # entities = {}
151
+ # entity_lookup = entity_data.get('data', {}).get('entityLookup', {})
152
+ # entity_items = entity_lookup.get('items', [])
153
+
154
+ # if hasattr(args, 'verbose') and args.verbose:
155
+ # print(f"Processing {len(entity_items)} {entity_type}s from entity lookup")
156
+ # if indexIdName:
157
+ # print(f"Using custom index field: {indexIdName}")
158
+
159
+ # for item in entity_items:
160
+ # entity = item.get('entity', {})
161
+ # entity_id = entity.get('id')
162
+ # helper_fields = item.get('helperFields', [])
163
+
164
+ # # Determine the index key to use
165
+ # index_key = entity_id # Default to entity ID
166
+ # custom_id = None
167
+
168
+ # if indexIdName and helper_fields:
169
+ # # Look for the custom ID in helperFields
170
+ # for field in helper_fields:
171
+ # if field.get('name') == indexIdName:
172
+ # custom_id = field.get('value')
173
+ # if custom_id:
174
+ # index_key = custom_id
175
+ # break
176
+
177
+ # if index_key:
178
+ # entity_data = {
179
+ # 'id': entity_id,
180
+ # 'name': entity.get('name', ''),
181
+ # 'type': entity.get('type', ''),
182
+ # 'description': item.get('description', ''),
183
+ # 'helperFields': helper_fields
184
+ # }
185
+
186
+ # # Add the custom index ID if it was found and used
187
+ # if custom_id and indexIdName:
188
+ # entity_data['indexId'] = custom_id
189
+ # entity_data['indexIdName'] = indexIdName
190
+
191
+ # entities[index_key] = entity_data
192
+
193
+ # if hasattr(args, 'verbose') and args.verbose and custom_id:
194
+ # print(f"Entity {entity_id} indexed by {indexIdName}: {custom_id}")
195
+
196
+ # if hasattr(args, 'verbose') and args.verbose:
197
+ # index_type = f"custom field '{indexIdName}'" if indexIdName else "entity ID"
198
+ # print(f"Successfully indexed {len(entities)} {entity_type}s by {index_type}")
199
+
200
+ # return entities
201
+
202
+ # except ApiException as e:
203
+ # raise Exception(f"{entity_type} lookup API call failed - {e}")
204
+ # except Exception as e:
205
+ # raise Exception(f"Unexpected error during {entity_type} lookup API call - {e}")
206
+
207
+ def makeCall(args, configuration, query):
208
+ # Create API client instance with params
209
+ instance = CallApi(ApiClient(configuration))
210
+ params = {
211
+ 'v': hasattr(args, 'verbose') and args.verbose, # verbose mode
212
+ 'f': 'json', # format
213
+ 'p': False, # pretty print
214
+ 't': False # test mode
215
+ }
216
+
217
+ try:
218
+ # Call the API directly
219
+ # NOTE: The API client (graphql_client/api_client_types.py lines 106-108)
220
+ # automatically prints error responses and exits on GraphQL errors.
221
+ # This means our custom error handling below may not be reached if there are GraphQL errors.
222
+ response = instance.call_api(query, params)
223
+ response = response[0] if response else {}
224
+
225
+ # Show raw API response in verbose mode
226
+ if hasattr(args, 'verbose') and args.verbose:
227
+ print("\n" + "=" * 80)
228
+ print("RAW API RESPONSE:")
229
+ print("=" * 80)
230
+ print(json.dumps(response, indent=2))
231
+ print("=" * 80 + "\n")
232
+
233
+ # Check for GraphQL errors first (may not be reached due to API client behavior)
234
+ if 'errors' in response:
235
+ error_messages = [error.get('message', 'Unknown error') for error in response['errors']]
236
+ raise Exception(f"API returned errors: {', '.join(error_messages)}")
237
+
238
+ if not response or 'data' not in response:
239
+ raise ValueError("Failed to retrieve data from API")
240
+
241
+ return response
242
+
243
+ except ApiException as e:
244
+ raise Exception(f"API call failed - {e}")
245
+ except Exception as e:
246
+ raise Exception(f"Unexpected error during API call - {e}")
247
+
248
+ def writeDataToFile(data, args, account_id=None, default_filename_template="data_{account_id}.json", default_directory="config_data"):
249
+ """
250
+ Write data to a file with flexible output path configuration
251
+
252
+ Args:
253
+ data: The data to write to file (will be JSON serialized)
254
+ args: Command line arguments containing output_file_path and verbose options
255
+ account_id: Optional account ID for default filename generation
256
+ default_filename_template: Template for default filename (use {account_id} placeholder)
257
+ default_directory: Default directory for output files
258
+
259
+ Returns:
260
+ str: The path of the file that was written
261
+
262
+ Raises:
263
+ Exception: If file writing fails
264
+ """
265
+ # Set up output file path
266
+ if hasattr(args, 'output_file_path') and args.output_file_path:
267
+ output_file = args.output_file_path
268
+ destination_dir = os.path.dirname(output_file)
269
+ if hasattr(args, 'verbose') and args.verbose:
270
+ print(f"Using output file path: {output_file}")
271
+ else:
272
+ destination_dir = default_directory
273
+ if account_id:
274
+ filename = default_filename_template.format(account_id=account_id)
275
+ else:
276
+ # If no account_id provided, remove the placeholder
277
+ filename = default_filename_template.replace("_{account_id}", "")
278
+ output_file = os.path.join(destination_dir, filename)
279
+ if hasattr(args, 'verbose') and args.verbose:
280
+ print(f"Using default path: {output_file}")
281
+
282
+ # Create destination directory if it doesn't exist
283
+ if destination_dir and not os.path.exists(destination_dir):
284
+ if hasattr(args, 'verbose') and args.verbose:
285
+ print(f"Creating directory: {destination_dir}")
286
+ os.makedirs(destination_dir)
287
+
288
+ try:
289
+ # Write the data to the file
290
+ with open(output_file, 'w', encoding='utf-8') as f:
291
+ json.dump(data, f, indent=4, ensure_ascii=False)
292
+
293
+ if hasattr(args, 'verbose') and args.verbose:
294
+ print(f"Successfully wrote data to: {output_file}")
295
+
296
+ return output_file
297
+
298
+ except Exception as e:
299
+ raise Exception(f"Failed to write data to file {output_file}: {str(e)}")
300
+
301
+ def getAccountID(args, configuration):
302
+ """
303
+ Get the account ID from command line arguments, configuration, or environment variable.
304
+
305
+ Args:
306
+ args: Command line arguments
307
+ configuration: API configuration object
308
+
309
+ Returns:
310
+ str: The account ID to use for API calls
311
+
312
+ Raises:
313
+ ValueError: If no account ID is provided or found
314
+ """
315
+ account_id = None
316
+ if hasattr(args, 'accountID') and args.accountID:
317
+ account_id = args.accountID
318
+ elif hasattr(configuration, 'accountID') and configuration.accountID:
319
+ account_id = configuration.accountID
320
+ else:
321
+ account_id = os.getenv('CATO_ACCOUNT_ID')
322
+
323
+ if not account_id:
324
+ raise ValueError("Account ID is required. Provide it using the -accountID flag or set CATO_ACCOUNT_ID environment variable.")
325
+
326
+ return account_id
327
+
328
+ def check_terraform_binary():
329
+ """Check if terraform binary is available"""
330
+ try:
331
+ result = subprocess.run(['terraform', '--version'], capture_output=True, text=True)
332
+ if result.returncode == 0:
333
+ return True, result.stdout.strip().split('\n')[0]
334
+ else:
335
+ return False, "Terraform binary not found or not working"
336
+ except FileNotFoundError:
337
+ return False, "Terraform binary not found in PATH"
338
+ except Exception as e:
339
+ return False, f"Error checking terraform binary: {e}"
340
+
341
+
342
+ def check_terraform_config_files():
343
+ """Check if Terraform configuration files exist in current directory"""
344
+ tf_files = glob.glob('*.tf') + glob.glob('*.tf.json')
345
+ if tf_files:
346
+ return True, tf_files
347
+ else:
348
+ return False, []
349
+
350
+
351
+ def check_terraform_init():
352
+ """Check if Terraform has been initialized"""
353
+ terraform_dir = Path('.terraform')
354
+ if terraform_dir.exists() and terraform_dir.is_dir():
355
+ # Check for providers
356
+ providers_dir = terraform_dir / 'providers'
357
+ if providers_dir.exists():
358
+ return True, "Terraform is initialized"
359
+ else:
360
+ return False, "Terraform directory exists but no providers found"
361
+ else:
362
+ return False, "Terraform not initialized (.terraform directory not found)"
363
+
364
+
365
+ def check_module_exists(module_name):
366
+ """Check if the specified module exists in Terraform configuration"""
367
+ try:
368
+ # Remove 'module.' prefix if present
369
+ clean_module_name = module_name.replace('module.', '')
370
+
371
+ # Method 1: Check .tf files directly for module definitions
372
+ tf_files = glob.glob('*.tf') + glob.glob('*.tf.json')
373
+ for tf_file in tf_files:
374
+ try:
375
+ with open(tf_file, 'r') as f:
376
+ content = f.read()
377
+ # Look for module "module_name" blocks
378
+ if f'module "{clean_module_name}"' in content or f"module '{clean_module_name}'" in content:
379
+ return True, f"Module '{clean_module_name}' found in {tf_file}"
380
+ except Exception as e:
381
+ print(f"Warning: Could not read {tf_file}: {e}")
382
+ continue
383
+
384
+ # Method 2: Try terraform show -json as fallback
385
+ try:
386
+ result = subprocess.run(
387
+ ['terraform', 'show', '-json'],
388
+ capture_output=True,
389
+ text=True,
390
+ cwd=Path.cwd()
391
+ )
392
+
393
+ if result.returncode == 0:
394
+ state_data = json.loads(result.stdout)
395
+
396
+ # Check if module exists in configuration
397
+ if 'configuration' in state_data and state_data['configuration']:
398
+ modules = state_data.get('configuration', {}).get('root_module', {}).get('module_calls', {})
399
+ if clean_module_name in modules:
400
+ return True, f"Module '{clean_module_name}' found in Terraform state"
401
+
402
+ # Also check in planned_values for modules
403
+ if 'planned_values' in state_data and state_data['planned_values']:
404
+ modules = state_data.get('planned_values', {}).get('root_module', {}).get('child_modules', [])
405
+ for module in modules:
406
+ module_addr = module.get('address', '')
407
+ if clean_module_name in module_addr:
408
+ return True, f"Module '{clean_module_name}' found in planned values"
409
+ except (subprocess.SubprocessError, json.JSONDecodeError) as e:
410
+ print(f"Warning: Could not check terraform state: {e}")
411
+
412
+ return False, f"Module '{clean_module_name}' not found in Terraform configuration files"
413
+
414
+ except Exception as e:
415
+ return False, f"Error checking module existence: {e}"
416
+
417
+
418
+ def validate_terraform_environment(module_name, verbose=False):
419
+ """Validate the complete Terraform environment"""
420
+ print("\n Validating Terraform environment...")
421
+
422
+ # 1. Check terraform binary
423
+ print("\n Checking Terraform binary...")
424
+ has_terraform, terraform_msg = check_terraform_binary()
425
+ if not has_terraform:
426
+ raise Exception(f" Terraform not available: {terraform_msg}")
427
+ if verbose:
428
+ print(f" {terraform_msg}")
429
+ else:
430
+ print(" Terraform binary found")
431
+
432
+ # 2. Check for configuration files
433
+ print("\n Checking Terraform configuration files...")
434
+ has_config, config_files = check_terraform_config_files()
435
+ if not has_config:
436
+ raise Exception(" No Terraform configuration files (.tf or .tf.json) found in current directory")
437
+ if verbose:
438
+ print(f" Found {len(config_files)} configuration files: {', '.join(config_files)}")
439
+ else:
440
+ print(f" Found {len(config_files)} Terraform configuration files")
441
+
442
+ # 3. Check if terraform is initialized
443
+ print("\n Checking Terraform initialization...")
444
+ is_initialized, init_msg = check_terraform_init()
445
+ if not is_initialized:
446
+ raise Exception(f" {init_msg}. Run 'terraform init' first.")
447
+ if verbose:
448
+ print(f" {init_msg}")
449
+ else:
450
+ print(" Terraform is initialized")
451
+
452
+ # 4. Check if the specified module exists
453
+ print(f"\n Checking if module '{module_name}' exists...")
454
+ module_exists, module_msg = check_module_exists(module_name)
455
+ if not module_exists:
456
+ raise Exception(f" {module_msg}. Please add the module to your Terraform configuration first.")
457
+ if verbose:
458
+ print(f" {module_msg}")
459
+ else:
460
+ print(f" Module '{module_name}' found")
461
+
462
+ # 5. Check if modules are properly installed by running terraform validate
463
+ print("\n Checking if modules are properly installed...")
464
+ try:
465
+ result = subprocess.run(
466
+ ['terraform', 'validate'],
467
+ capture_output=True,
468
+ text=True,
469
+ cwd=Path.cwd()
470
+ )
471
+
472
+ if result.returncode != 0:
473
+ error_output = result.stderr.strip()
474
+ if "module is not yet installed" in error_output or "Module not installed" in error_output:
475
+ raise Exception(f" Terraform modules are not installed. Please run 'terraform init' to install all required modules.")
476
+ else:
477
+ raise Exception(f" Terraform validation failed:\n\n{error_output}")
478
+
479
+ print(" All modules are properly installed")
480
+
481
+ except subprocess.SubprocessError as e:
482
+ raise Exception(f" Failed to validate Terraform configuration: {e}")
483
+
484
+ print("\n All Terraform environment checks passed!")
485
+
486
+
487
+
488
+ def check_terraform_config_files():
489
+ """Check if Terraform configuration files exist in current directory"""
490
+ tf_files = glob.glob('*.tf') + glob.glob('*.tf.json')
491
+ if tf_files:
492
+ return True, tf_files
493
+ else:
494
+ return False, []
495
+
496
+
497
+ def check_terraform_init():
498
+ """Check if Terraform has been initialized"""
499
+ terraform_dir = Path('.terraform')
500
+ if terraform_dir.exists() and terraform_dir.is_dir():
501
+ # Check for providers
502
+ providers_dir = terraform_dir / 'providers'
503
+ if providers_dir.exists():
504
+ return True, "Terraform is initialized"
505
+ else:
506
+ return False, "Terraform directory exists but no providers found"
507
+ else:
508
+ return False, "Terraform not initialized (.terraform directory not found)"
509
+
510
+
511
+ def check_module_exists(module_name):
512
+ """Check if the specified module exists in Terraform configuration"""
513
+ try:
514
+ # Remove 'module.' prefix if present
515
+ clean_module_name = module_name.replace('module.', '')
516
+
517
+ # Method 1: Check .tf files directly for module definitions
518
+ tf_files = glob.glob('*.tf') + glob.glob('*.tf.json')
519
+ for tf_file in tf_files:
520
+ try:
521
+ with open(tf_file, 'r') as f:
522
+ content = f.read()
523
+ # Look for module "module_name" blocks
524
+ if f'module "{clean_module_name}"' in content or f"module '{clean_module_name}'" in content:
525
+ return True, f"Module '{clean_module_name}' found in {tf_file}"
526
+ except Exception as e:
527
+ print(f"Warning: Could not read {tf_file}: {e}")
528
+ continue
529
+
530
+ # Method 2: Try terraform show -json as fallback
531
+ try:
532
+ result = subprocess.run(
533
+ ['terraform', 'show', '-json'],
534
+ capture_output=True,
535
+ text=True,
536
+ cwd=Path.cwd()
537
+ )
538
+
539
+ if result.returncode == 0:
540
+ state_data = json.loads(result.stdout)
541
+
542
+ # Check if module exists in configuration
543
+ if 'configuration' in state_data and state_data['configuration']:
544
+ modules = state_data.get('configuration', {}).get('root_module', {}).get('module_calls', {})
545
+ if clean_module_name in modules:
546
+ return True, f"Module '{clean_module_name}' found in Terraform state"
547
+
548
+ # Also check in planned_values for modules
549
+ if 'planned_values' in state_data and state_data['planned_values']:
550
+ modules = state_data.get('planned_values', {}).get('root_module', {}).get('child_modules', [])
551
+ for module in modules:
552
+ module_addr = module.get('address', '')
553
+ if clean_module_name in module_addr:
554
+ return True, f"Module '{clean_module_name}' found in planned values"
555
+ except (subprocess.SubprocessError, json.JSONDecodeError) as e:
556
+ print(f"Warning: Could not check terraform state: {e}")
557
+
558
+ return False, f"Module '{clean_module_name}' not found in Terraform configuration files"
559
+
560
+ except Exception as e:
561
+ return False, f"Error checking module existence: {e}"
@@ -0,0 +1,42 @@
1
+ import catocli.parsers.custom.export_rules.export_rules as export_rules
2
+
3
+ def export_rules_parse(subparsers):
4
+ """Create export command parsers"""
5
+
6
+ # Create the main export parser
7
+ export_parser = subparsers.add_parser('export', help='Export data to various formats', usage='catocli export <operation> [options]')
8
+ export_subparsers = export_parser.add_subparsers(description='valid export operations', help='additional help')
9
+
10
+ # Add sites export functionality
11
+ from catocli.parsers.custom.export_sites import export_sites_parse
12
+ export_sites_parse(export_subparsers)
13
+
14
+ # Add if_rules command
15
+ if_rules_parser = export_subparsers.add_parser(
16
+ 'if_rules',
17
+ help='Export Internet Firewall rules to JSON format',
18
+ usage='catocli export if_rules [-accountID <account_id>] [options]'
19
+ )
20
+
21
+ if_rules_parser.add_argument('-accountID', help='Account ID to export rules from (uses CATO_ACCOUNT_ID environment variable if not specified)', required=False)
22
+ if_rules_parser.add_argument('--output-file-path', help='Full path including filename and extension for output file. If not specified, uses default: config_data/all_ifw_rules_and_sections_{account_id}.json')
23
+ if_rules_parser.add_argument('--append-timestamp', action='store_true', help='Append timestamp to the filename after account ID (format: YYYY-MM-DD_HH-MM-SS)')
24
+ if_rules_parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
25
+
26
+ if_rules_parser.set_defaults(func=export_rules.export_if_rules_to_json)
27
+
28
+ # Add wf_rules command
29
+ wf_rules_parser = export_subparsers.add_parser(
30
+ 'wf_rules',
31
+ help='Export WAN Firewall rules to JSON format',
32
+ usage='catocli export wf_rules [-accountID <account_id>] [options]'
33
+ )
34
+
35
+ wf_rules_parser.add_argument('-accountID', help='Account ID to export rules from (uses CATO_ACCOUNT_ID environment variable if not specified)', required=False)
36
+ wf_rules_parser.add_argument('--output-file-path', help='Full path including filename and extension for output file. If not specified, uses default: config_data/all_wf_rules_and_sections_{account_id}.json')
37
+ wf_rules_parser.add_argument('--append-timestamp', action='store_true', help='Append timestamp to the filename after account ID (format: YYYY-MM-DD_HH-MM-SS)')
38
+ wf_rules_parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
39
+
40
+ wf_rules_parser.set_defaults(func=export_rules.export_wf_rules_to_json)
41
+
42
+ return export_parser