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,115 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Configure command parser for Cato CLI
4
+ Handles profile creation, listing, and switching
5
+ """
6
+
7
+ import argparse
8
+ from .configure import (
9
+ configure_profile,
10
+ list_profiles,
11
+ set_profile,
12
+ delete_profile,
13
+ show_profile
14
+ )
15
+
16
+
17
+ def configure_parse(subparsers):
18
+ """Create configure command parsers"""
19
+
20
+ # Create the main configure parser
21
+ configure_parser = subparsers.add_parser(
22
+ 'configure',
23
+ help='Configure Cato CLI credentials and profiles',
24
+ usage='catocli configure <subcommand> [options]'
25
+ )
26
+ configure_subparsers = configure_parser.add_subparsers(
27
+ description='Configure operations',
28
+ help='Profile management operations'
29
+ )
30
+
31
+ # Configure profile command
32
+ config_parser = configure_subparsers.add_parser(
33
+ 'set',
34
+ help='Configure a profile with credentials',
35
+ usage='catocli configure set [--profile PROFILE] [options]'
36
+ )
37
+ config_parser.add_argument(
38
+ '--profile',
39
+ default='default',
40
+ help='Profile name to configure (default: default)'
41
+ )
42
+ config_parser.add_argument(
43
+ '--endpoint',
44
+ help='Cato API endpoint URL (default: https://api.catonetworks.com/api/v1/graphql2)'
45
+ )
46
+ config_parser.add_argument(
47
+ '--cato-token',
48
+ help='Cato API token'
49
+ )
50
+ config_parser.add_argument(
51
+ '--account-id',
52
+ help='Cato account ID'
53
+ )
54
+ config_parser.add_argument(
55
+ '--interactive',
56
+ action='store_true',
57
+ help='Interactive configuration mode'
58
+ )
59
+ config_parser.add_argument(
60
+ '--skip-validation',
61
+ action='store_true',
62
+ help='Skip credential validation (save without testing)'
63
+ )
64
+ config_parser.set_defaults(func=configure_profile)
65
+
66
+ # List profiles command
67
+ list_parser = configure_subparsers.add_parser(
68
+ 'list',
69
+ help='List all configured profiles',
70
+ usage='catocli configure list'
71
+ )
72
+ list_parser.set_defaults(func=list_profiles)
73
+
74
+ # Use/switch profile command
75
+ use_parser = configure_subparsers.add_parser(
76
+ 'use',
77
+ help='Set the active profile',
78
+ usage='catocli configure use <profile>'
79
+ )
80
+ use_parser.add_argument(
81
+ 'profile',
82
+ help='Profile name to activate'
83
+ )
84
+ use_parser.set_defaults(func=set_profile)
85
+
86
+ # Show current profile command
87
+ show_parser = configure_subparsers.add_parser(
88
+ 'show',
89
+ help='Show current profile configuration',
90
+ usage='catocli configure show [--profile PROFILE]'
91
+ )
92
+ show_parser.add_argument(
93
+ '--profile',
94
+ help='Profile name to show (default: current active profile)'
95
+ )
96
+ show_parser.set_defaults(func=show_profile)
97
+
98
+ # Delete profile command
99
+ delete_parser = configure_subparsers.add_parser(
100
+ 'delete',
101
+ help='Delete a profile',
102
+ usage='catocli configure delete <profile>'
103
+ )
104
+ delete_parser.add_argument(
105
+ 'profile',
106
+ help='Profile name to delete'
107
+ )
108
+ delete_parser.add_argument(
109
+ '--force',
110
+ action='store_true',
111
+ help='Force deletion without confirmation'
112
+ )
113
+ delete_parser.set_defaults(func=delete_profile)
114
+
115
+ return configure_parser
@@ -0,0 +1,307 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Configure command implementation for Cato CLI
4
+ Implements profile creation, listing, switching, and management
5
+ """
6
+
7
+ import getpass
8
+ import sys
9
+ import json
10
+ from graphql_client import Configuration
11
+ from graphql_client.api_client import ApiException
12
+ from graphql_client.api.call_api import ApiClient, CallApi
13
+ from ...Utils.profile_manager import get_profile_manager
14
+
15
+
16
+ def test_credentials(endpoint, cato_token, account_id):
17
+ """Test credentials by making an entityLookup API call"""
18
+ try:
19
+ print("Testing credentials...")
20
+
21
+ # Create a temporary configuration
22
+ test_config = Configuration()
23
+ test_config.verify_ssl = False
24
+ test_config.debug = False
25
+ test_config.version = "1.0.0" # Required for API client
26
+ test_config.api_key["x-api-key"] = cato_token
27
+ test_config.host = endpoint
28
+ test_config.accountID = account_id
29
+
30
+ # Make a simple entityLookup call to test credentials
31
+ instance = CallApi(ApiClient(test_config))
32
+ response = instance.call_api({
33
+ "query": "query entityLookup($accountID: ID!, $type: EntityType!) { entityLookup(accountID: $accountID, type: $type) { items { entity { id name } } } }",
34
+ "variables": {"accountID": account_id, "type": "country"}
35
+ }, {})
36
+ result = response[0] if response else None
37
+
38
+ # Check if the call was successful
39
+ if result and result.get('data') is not None:
40
+ print("✓ Credentials validated successfully")
41
+ return True, "Credentials are valid"
42
+ elif result and result.get('errors'):
43
+ error_msg = result['errors'][0].get('message', 'Unknown API error')
44
+ return False, f"API error: {error_msg}"
45
+ elif result is None:
46
+ return False, "No response from API"
47
+ else:
48
+ return False, f"Invalid API response: {result}"
49
+
50
+ except ApiException as e:
51
+ if e.status == 401:
52
+ return False, "Invalid API token"
53
+ elif e.status == 403:
54
+ return False, "Access denied - check account ID and permissions"
55
+ else:
56
+ return False, f"API error (status {e.status}): {str(e)}"
57
+ except Exception as e:
58
+ return False, f"Connection error: {str(e)}"
59
+
60
+
61
+ def configure_profile(args, configuration=None):
62
+ """Configure a profile with credentials"""
63
+ pm = get_profile_manager()
64
+ profile_name = args.profile
65
+
66
+ try:
67
+ # Interactive mode
68
+ if args.interactive or (not args.cato_token and not args.account_id and not args.endpoint):
69
+ print(f"Configuring profile '{profile_name}'")
70
+ print("Leave blank to keep existing values (if any)")
71
+ print()
72
+
73
+ # Get current values if profile exists
74
+ current_config = pm.get_profile_config(profile_name) or {}
75
+
76
+ # Get endpoint
77
+ current_endpoint = current_config.get('endpoint', pm.default_endpoint)
78
+ endpoint_input = input(f"Cato API Endpoint [{current_endpoint}]: ").strip()
79
+ endpoint = endpoint_input if endpoint_input else current_endpoint
80
+
81
+ # Get token
82
+ current_token = current_config.get('cato_token', '')
83
+ if current_token:
84
+ token_prompt = f"Cato API Token [****{current_token[-4:]}]: "
85
+ else:
86
+ token_prompt = "Cato API Token: "
87
+ token_input = getpass.getpass(token_prompt).strip()
88
+ cato_token = token_input if token_input else current_token
89
+
90
+ # Get account ID
91
+ current_account = current_config.get('account_id', '')
92
+ account_input = input(f"Account ID [{current_account}]: ").strip()
93
+ account_id = account_input if account_input else current_account
94
+
95
+ else:
96
+ # Non-interactive mode
97
+ endpoint = args.endpoint
98
+ cato_token = getattr(args, 'cato_token', None)
99
+ account_id = getattr(args, 'account_id', None)
100
+
101
+ # Validate required fields
102
+ if not cato_token or not account_id:
103
+ current_config = pm.get_profile_config(profile_name) or {}
104
+ if not cato_token:
105
+ cato_token = current_config.get('cato_token')
106
+ if not account_id:
107
+ account_id = current_config.get('account_id')
108
+
109
+ if not cato_token:
110
+ print("ERROR: Cato API token is required")
111
+ return [{"success": False, "error": "Missing cato_token"}]
112
+
113
+ if not account_id:
114
+ print("ERROR: Account ID is required")
115
+ return [{"success": False, "error": "Missing account_id"}]
116
+
117
+ # Set default endpoint if not provided
118
+ if not endpoint:
119
+ endpoint = pm.default_endpoint
120
+
121
+ # Test credentials before saving (unless validation is skipped)
122
+ if hasattr(args, 'skip_validation') and args.skip_validation:
123
+ print("⚠️ Skipping credential validation")
124
+ else:
125
+ is_valid, error_message = test_credentials(endpoint, cato_token, account_id)
126
+ if not is_valid:
127
+ print(f"ERROR: {error_message}")
128
+ print("Profile not saved. Please check your credentials and try again.")
129
+ print("(Use --skip-validation to save without testing)")
130
+ return [{"success": False, "error": f"Credential validation failed: {error_message}"}]
131
+
132
+ # Create the profile
133
+ success = pm.create_profile(
134
+ profile_name=profile_name,
135
+ endpoint=endpoint,
136
+ cato_token=cato_token,
137
+ account_id=account_id
138
+ )
139
+
140
+ if success:
141
+ print(f"Profile '{profile_name}' configured successfully!")
142
+ if profile_name == 'default' or len(pm.list_profiles()) == 1:
143
+ pm.set_current_profile(profile_name)
144
+ print(f"Set '{profile_name}' as the active profile")
145
+ else:
146
+ print(f"Failed to configure profile '{profile_name}'")
147
+ return [{"success": False, "error": "Failed to create profile"}]
148
+
149
+ return [{"success": True, "profile": profile_name}]
150
+
151
+ except KeyboardInterrupt:
152
+ print("\nOperation cancelled")
153
+ return [{"success": False, "error": "Operation cancelled by user"}]
154
+ except Exception as e:
155
+ print(f"ERROR: {e}")
156
+ return [{"success": False, "error": str(e)}]
157
+
158
+
159
+ def list_profiles(args, configuration=None):
160
+ """List all configured profiles"""
161
+ pm = get_profile_manager()
162
+
163
+ try:
164
+ profiles = pm.list_profiles()
165
+ current_profile = pm.get_current_profile()
166
+
167
+ if not profiles:
168
+ print("No profiles configured.")
169
+ print("Run 'catocli configure set' to create your first profile.")
170
+ return [{"success": True, "profiles": []}]
171
+
172
+ print("Available profiles:")
173
+ print()
174
+
175
+ for profile in profiles:
176
+ is_current = profile == current_profile
177
+ status = " (current)" if is_current else ""
178
+
179
+ config = pm.get_profile_config(profile)
180
+ endpoint = config.get('endpoint', 'N/A')
181
+ account_id = config.get('account_id', 'N/A')
182
+
183
+ print(f" {profile}{status}")
184
+ print(f" Endpoint: {endpoint}")
185
+ print(f" Account ID: {account_id}")
186
+ print()
187
+
188
+ return [{"success": True, "profiles": profiles, "current": current_profile}]
189
+
190
+ except Exception as e:
191
+ print(f"ERROR: {e}")
192
+ return [{"success": False, "error": str(e)}]
193
+
194
+
195
+ def set_profile(args, configuration=None):
196
+ """Set the active profile"""
197
+ pm = get_profile_manager()
198
+ profile_name = args.profile
199
+
200
+ try:
201
+ # Check if profile exists
202
+ if profile_name not in pm.list_profiles():
203
+ print(f"ERROR: Profile '{profile_name}' does not exist.")
204
+ print("Available profiles:")
205
+ for p in pm.list_profiles():
206
+ print(f" {p}")
207
+ return [{"success": False, "error": "Profile not found"}]
208
+
209
+ # Validate profile has required credentials
210
+ is_valid, message = pm.validate_profile(profile_name)
211
+ if not is_valid:
212
+ print(f"ERROR: {message}")
213
+ print(f"Run 'catocli configure set --profile {profile_name}' to update the profile.")
214
+ return [{"success": False, "error": message}]
215
+
216
+ # Set as current profile
217
+ pm.set_current_profile(profile_name)
218
+ print(f"Switched to profile '{profile_name}'")
219
+
220
+ return [{"success": True, "profile": profile_name}]
221
+
222
+ except Exception as e:
223
+ print(f"ERROR: {e}")
224
+ return [{"success": False, "error": str(e)}]
225
+
226
+
227
+ def show_profile(args, configuration=None):
228
+ """Show current profile configuration"""
229
+ pm = get_profile_manager()
230
+
231
+ try:
232
+ profile_name = args.profile if hasattr(args, 'profile') and args.profile else pm.get_current_profile()
233
+
234
+ # Check if profile exists
235
+ config = pm.get_profile_config(profile_name)
236
+ if not config:
237
+ print(f"Profile '{profile_name}' not found.")
238
+ return [{"success": False, "error": "Profile not found"}]
239
+
240
+ print(f"Profile: {profile_name}")
241
+ print(f"Endpoint: {config.get('endpoint', 'N/A')}")
242
+ print(f"Account ID: {config.get('account_id', 'N/A')}")
243
+
244
+ # Show token status without revealing it
245
+ token = config.get('cato_token', '')
246
+ if token:
247
+ print(f"Token: ****{token[-4:]} (configured)")
248
+ else:
249
+ print("Token: (not configured)")
250
+
251
+ # Show if this is the current profile
252
+ current_profile = pm.get_current_profile()
253
+ if profile_name == current_profile:
254
+ print("Status: Current active profile")
255
+ else:
256
+ print(f"Status: Available (current: {current_profile})")
257
+
258
+ # Create masked config for JSON output
259
+ masked_config = config.copy()
260
+ if masked_config.get('cato_token'):
261
+ masked_config['cato_token'] = f"****{masked_config['cato_token'][-4:]}"
262
+
263
+ return [{"success": True, "profile": profile_name, "config": masked_config}]
264
+
265
+ except Exception as e:
266
+ print(f"ERROR: {e}")
267
+ return [{"success": False, "error": str(e)}]
268
+
269
+
270
+ def delete_profile(args, configuration=None):
271
+ """Delete a profile"""
272
+ pm = get_profile_manager()
273
+ profile_name = args.profile
274
+
275
+ try:
276
+ # Check if profile exists
277
+ if profile_name not in pm.list_profiles():
278
+ print(f"Profile '{profile_name}' does not exist.")
279
+ return [{"success": False, "error": "Profile not found"}]
280
+
281
+ # Check if it's the current profile
282
+ current_profile = pm.get_current_profile()
283
+ if profile_name == current_profile:
284
+ print(f"Cannot delete the current active profile '{profile_name}'.")
285
+ print("Switch to another profile first using 'catocli configure use <profile>'")
286
+ return [{"success": False, "error": "Cannot delete active profile"}]
287
+
288
+ # Confirm deletion unless forced
289
+ if not args.force:
290
+ response = input(f"Are you sure you want to delete profile '{profile_name}'? (y/N): ").strip().lower()
291
+ if response != 'y':
292
+ print("Deletion cancelled.")
293
+ return [{"success": False, "error": "Deletion cancelled by user"}]
294
+
295
+ # Delete the profile
296
+ success = pm.delete_profile(profile_name)
297
+ if success:
298
+ print(f"Profile '{profile_name}' deleted successfully.")
299
+ else:
300
+ print(f"Failed to delete profile '{profile_name}'.")
301
+ return [{"success": False, "error": "Failed to delete profile"}]
302
+
303
+ return [{"success": True, "deleted_profile": profile_name}]
304
+
305
+ except Exception as e:
306
+ print(f"ERROR: {e}")
307
+ return [{"success": False, "error": str(e)}]
@@ -0,0 +1,57 @@
1
+
2
+ import catocli.parsers.custom.customLib as customLib
3
+ from catocli.parsers.custom.export_rules import export_rules_parse
4
+ from catocli.parsers.custom.import_rules_to_tf import rule_import_parse
5
+ from catocli.parsers.custom.import_sites_to_tf import site_import_parse
6
+ from catocli.parsers.configure import configure_parse
7
+ from catocli.parsers.custom.export_sites import export_sites_parse
8
+
9
+ def custom_parse(subparsers):
10
+ entityTypes = ["account","admin","allocatedIP","any","availablePooledUsage","availableSiteUsage","dhcpRelayGroup","groupSubscription","host","lanFirewall","localRouting","location","mailingListSubscription","networkInterface","portProtocol","simpleService","site","siteRange","timezone","vpnUser","webhookSubscription"]
11
+ entity_parser = subparsers.add_parser('entity', help='Entity Lookup', usage='catocli entity <operationName> [options]')
12
+ entity_subparsers = entity_parser.add_subparsers(description='valid subcommands', help='additional help')
13
+
14
+ for entity in entityTypes:
15
+ item_parser = entity_subparsers.add_parser(entity, help="entityLookup() for type: "+entity, usage='catocli entity '+entity+' <operationName> [options]')
16
+ item_subparsers = item_parser.add_subparsers(description='valid subcommands', help='additional help')
17
+
18
+ item_list_parser = item_subparsers.add_parser('list',
19
+ help='entity'+entity+' list',
20
+ usage=get_help_custom("entity_"+entity+"_list"))
21
+
22
+ item_list_parser.add_argument('-accountID', help='The Account ID.')
23
+ item_list_parser.add_argument('-s', help='Search string', default='', nargs='?')
24
+ item_list_parser.add_argument('-f', default="csv", choices=["json","csv"], nargs='?',
25
+ help='Specify format for output')
26
+ item_list_parser.add_argument('-t', const=True, default=False, nargs='?',
27
+ help='Print test request preview without sending api call')
28
+ item_list_parser.add_argument('-v', const=True, default=False, nargs='?',
29
+ help='Verbose output')
30
+ item_list_parser.add_argument('-p', const=True, default=False, nargs='?',
31
+ help='Pretty print')
32
+
33
+ item_list_parser.set_defaults(func=customLib.entityTypeList,operation_name=entity)
34
+
35
+ # Add additional custom parsers here
36
+ export_rules_parse(subparsers)
37
+ import_parser = rule_import_parse(subparsers)
38
+ site_import_parse(subparsers, import_parser)
39
+ configure_parse(subparsers)
40
+
41
+ def get_help_custom(path):
42
+ matchCmd = "catocli "+path.replace("_"," ")
43
+ import os
44
+ pwd = os.path.dirname(__file__)
45
+ abs_path = os.path.join(pwd, "README.md")
46
+ new_line = "\nEXAMPLES:\n"
47
+ lines = open(abs_path, "r").readlines()
48
+ for line in lines:
49
+ if f"{matchCmd}" in line:
50
+ clean_line = line.replace("<br /><br />", "").replace("`","")
51
+ new_line += f"{clean_line}\n"
52
+ # matchArg = path.replace("_",".")
53
+ # for line in lines:
54
+ # if f"`{matchArg}" in line:
55
+ # clean_line = line.replace("<br /><br />", "").replace("`","")
56
+ # new_line += f"{clean_line}\n"
57
+ return new_line