catocli 2.1.1__py3-none-any.whl → 2.1.3__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 (564) hide show
  1. catocli/Utils/clidriver.py +207 -211
  2. catocli/Utils/cliutils.py +178 -0
  3. catocli/__init__.py +1 -1
  4. catocli/parsers/custom/customLib.py +1 -1
  5. catocli/parsers/custom/export_sites/export_sites.py +121 -133
  6. catocli/parsers/customParserApiClient.py +1195 -0
  7. catocli/parsers/custom_private/__init__.py +2 -14
  8. catocli/parsers/mutation_accountManagement/__init__.py +45 -58
  9. catocli/parsers/mutation_accountManagement_addAccount/README.md +7 -5
  10. catocli/parsers/mutation_accountManagement_removeAccount/README.md +4 -5
  11. catocli/parsers/mutation_accountManagement_updateAccount/README.md +7 -5
  12. catocli/parsers/mutation_admin/__init__.py +84 -45
  13. catocli/parsers/mutation_admin_addAdmin/README.md +7 -5
  14. catocli/parsers/mutation_admin_addServicePrincipalAdmin/README.md +19 -0
  15. catocli/parsers/mutation_admin_removeAdmin/README.md +7 -5
  16. catocli/parsers/mutation_admin_removeServicePrincipalAdmin/README.md +19 -0
  17. catocli/parsers/mutation_admin_updateAdmin/README.md +8 -6
  18. catocli/parsers/mutation_admin_updateServicePrincipalAdmin/README.md +20 -0
  19. catocli/parsers/mutation_container/__init__.py +135 -135
  20. catocli/parsers/mutation_container_delete/README.md +7 -5
  21. catocli/parsers/mutation_container_fqdn_addValues/README.md +7 -5
  22. catocli/parsers/mutation_container_fqdn_createFromFile/README.md +7 -5
  23. catocli/parsers/mutation_container_fqdn_removeValues/README.md +7 -5
  24. catocli/parsers/mutation_container_fqdn_updateFromFile/README.md +7 -5
  25. catocli/parsers/mutation_container_ipAddressRange_addValues/README.md +7 -5
  26. catocli/parsers/mutation_container_ipAddressRange_createFromFile/README.md +7 -5
  27. catocli/parsers/mutation_container_ipAddressRange_removeValues/README.md +7 -5
  28. catocli/parsers/mutation_container_ipAddressRange_updateFromFile/README.md +7 -5
  29. catocli/parsers/mutation_enterpriseDirectory/README.md +7 -0
  30. catocli/parsers/mutation_enterpriseDirectory/__init__.py +61 -0
  31. catocli/parsers/mutation_enterpriseDirectory_archiveLocation/README.md +19 -0
  32. catocli/parsers/mutation_enterpriseDirectory_createLocation/README.md +19 -0
  33. catocli/parsers/mutation_enterpriseDirectory_restoreLocation/README.md +19 -0
  34. catocli/parsers/mutation_enterpriseDirectory_updateLocation/README.md +19 -0
  35. catocli/parsers/mutation_groups/__init__.py +45 -45
  36. catocli/parsers/mutation_groups_createGroup/README.md +8 -6
  37. catocli/parsers/mutation_groups_deleteGroup/README.md +8 -6
  38. catocli/parsers/mutation_groups_updateGroup/README.md +8 -6
  39. catocli/parsers/mutation_hardware/__init__.py +16 -16
  40. catocli/parsers/mutation_hardware_updateHardwareShipping/README.md +7 -5
  41. catocli/parsers/mutation_policy/__init__.py +1302 -1302
  42. catocli/parsers/mutation_policy_appTenantRestriction_addRule/README.md +8 -6
  43. catocli/parsers/mutation_policy_appTenantRestriction_addSection/README.md +8 -6
  44. catocli/parsers/mutation_policy_appTenantRestriction_createPolicyRevision/README.md +8 -6
  45. catocli/parsers/mutation_policy_appTenantRestriction_discardPolicyRevision/README.md +8 -6
  46. catocli/parsers/mutation_policy_appTenantRestriction_moveRule/README.md +8 -6
  47. catocli/parsers/mutation_policy_appTenantRestriction_moveSection/README.md +8 -6
  48. catocli/parsers/mutation_policy_appTenantRestriction_publishPolicyRevision/README.md +8 -6
  49. catocli/parsers/mutation_policy_appTenantRestriction_removeRule/README.md +8 -6
  50. catocli/parsers/mutation_policy_appTenantRestriction_removeSection/README.md +8 -6
  51. catocli/parsers/mutation_policy_appTenantRestriction_updatePolicy/README.md +8 -6
  52. catocli/parsers/mutation_policy_appTenantRestriction_updateRule/README.md +8 -6
  53. catocli/parsers/mutation_policy_appTenantRestriction_updateSection/README.md +8 -6
  54. catocli/parsers/mutation_policy_dynamicIpAllocation_addRule/README.md +8 -6
  55. catocli/parsers/mutation_policy_dynamicIpAllocation_addSection/README.md +8 -6
  56. catocli/parsers/mutation_policy_dynamicIpAllocation_createPolicyRevision/README.md +8 -6
  57. catocli/parsers/mutation_policy_dynamicIpAllocation_discardPolicyRevision/README.md +8 -6
  58. catocli/parsers/mutation_policy_dynamicIpAllocation_moveRule/README.md +8 -6
  59. catocli/parsers/mutation_policy_dynamicIpAllocation_moveSection/README.md +8 -6
  60. catocli/parsers/mutation_policy_dynamicIpAllocation_publishPolicyRevision/README.md +8 -6
  61. catocli/parsers/mutation_policy_dynamicIpAllocation_removeRule/README.md +8 -6
  62. catocli/parsers/mutation_policy_dynamicIpAllocation_removeSection/README.md +8 -6
  63. catocli/parsers/mutation_policy_dynamicIpAllocation_updatePolicy/README.md +8 -6
  64. catocli/parsers/mutation_policy_dynamicIpAllocation_updateRule/README.md +8 -6
  65. catocli/parsers/mutation_policy_dynamicIpAllocation_updateSection/README.md +8 -6
  66. catocli/parsers/mutation_policy_internetFirewall_addRule/README.md +8 -6
  67. catocli/parsers/mutation_policy_internetFirewall_addSection/README.md +8 -6
  68. catocli/parsers/mutation_policy_internetFirewall_createPolicyRevision/README.md +8 -6
  69. catocli/parsers/mutation_policy_internetFirewall_discardPolicyRevision/README.md +8 -6
  70. catocli/parsers/mutation_policy_internetFirewall_moveRule/README.md +8 -6
  71. catocli/parsers/mutation_policy_internetFirewall_moveSection/README.md +8 -6
  72. catocli/parsers/mutation_policy_internetFirewall_publishPolicyRevision/README.md +8 -6
  73. catocli/parsers/mutation_policy_internetFirewall_removeRule/README.md +8 -6
  74. catocli/parsers/mutation_policy_internetFirewall_removeSection/README.md +8 -6
  75. catocli/parsers/mutation_policy_internetFirewall_updatePolicy/README.md +8 -6
  76. catocli/parsers/mutation_policy_internetFirewall_updateRule/README.md +8 -6
  77. catocli/parsers/mutation_policy_internetFirewall_updateSection/README.md +8 -6
  78. catocli/parsers/mutation_policy_remotePortFwd_addRule/README.md +8 -6
  79. catocli/parsers/mutation_policy_remotePortFwd_addSection/README.md +8 -6
  80. catocli/parsers/mutation_policy_remotePortFwd_createPolicyRevision/README.md +8 -6
  81. catocli/parsers/mutation_policy_remotePortFwd_discardPolicyRevision/README.md +8 -6
  82. catocli/parsers/mutation_policy_remotePortFwd_moveRule/README.md +8 -6
  83. catocli/parsers/mutation_policy_remotePortFwd_moveSection/README.md +8 -6
  84. catocli/parsers/mutation_policy_remotePortFwd_publishPolicyRevision/README.md +8 -6
  85. catocli/parsers/mutation_policy_remotePortFwd_removeRule/README.md +8 -6
  86. catocli/parsers/mutation_policy_remotePortFwd_removeSection/README.md +8 -6
  87. catocli/parsers/mutation_policy_remotePortFwd_updatePolicy/README.md +8 -6
  88. catocli/parsers/mutation_policy_remotePortFwd_updateRule/README.md +8 -6
  89. catocli/parsers/mutation_policy_remotePortFwd_updateSection/README.md +8 -6
  90. catocli/parsers/mutation_policy_socketLan_addRule/README.md +8 -6
  91. catocli/parsers/mutation_policy_socketLan_addSection/README.md +8 -6
  92. catocli/parsers/mutation_policy_socketLan_createPolicyRevision/README.md +8 -6
  93. catocli/parsers/mutation_policy_socketLan_discardPolicyRevision/README.md +8 -6
  94. catocli/parsers/mutation_policy_socketLan_moveRule/README.md +8 -6
  95. catocli/parsers/mutation_policy_socketLan_moveSection/README.md +8 -6
  96. catocli/parsers/mutation_policy_socketLan_publishPolicyRevision/README.md +8 -6
  97. catocli/parsers/mutation_policy_socketLan_removeRule/README.md +8 -6
  98. catocli/parsers/mutation_policy_socketLan_removeSection/README.md +8 -6
  99. catocli/parsers/mutation_policy_socketLan_updatePolicy/README.md +8 -6
  100. catocli/parsers/mutation_policy_socketLan_updateRule/README.md +8 -6
  101. catocli/parsers/mutation_policy_socketLan_updateSection/README.md +8 -6
  102. catocli/parsers/mutation_policy_terminalServer_addRule/README.md +8 -6
  103. catocli/parsers/mutation_policy_terminalServer_addSection/README.md +8 -6
  104. catocli/parsers/mutation_policy_terminalServer_createPolicyRevision/README.md +8 -6
  105. catocli/parsers/mutation_policy_terminalServer_discardPolicyRevision/README.md +8 -6
  106. catocli/parsers/mutation_policy_terminalServer_moveRule/README.md +8 -6
  107. catocli/parsers/mutation_policy_terminalServer_moveSection/README.md +8 -6
  108. catocli/parsers/mutation_policy_terminalServer_publishPolicyRevision/README.md +8 -6
  109. catocli/parsers/mutation_policy_terminalServer_removeRule/README.md +8 -6
  110. catocli/parsers/mutation_policy_terminalServer_removeSection/README.md +8 -6
  111. catocli/parsers/mutation_policy_terminalServer_updatePolicy/README.md +8 -6
  112. catocli/parsers/mutation_policy_terminalServer_updateRule/README.md +8 -6
  113. catocli/parsers/mutation_policy_terminalServer_updateSection/README.md +8 -6
  114. catocli/parsers/mutation_policy_wanFirewall_addRule/README.md +8 -6
  115. catocli/parsers/mutation_policy_wanFirewall_addSection/README.md +8 -6
  116. catocli/parsers/mutation_policy_wanFirewall_createPolicyRevision/README.md +8 -6
  117. catocli/parsers/mutation_policy_wanFirewall_discardPolicyRevision/README.md +8 -6
  118. catocli/parsers/mutation_policy_wanFirewall_moveRule/README.md +8 -6
  119. catocli/parsers/mutation_policy_wanFirewall_moveSection/README.md +8 -6
  120. catocli/parsers/mutation_policy_wanFirewall_publishPolicyRevision/README.md +8 -6
  121. catocli/parsers/mutation_policy_wanFirewall_removeRule/README.md +8 -6
  122. catocli/parsers/mutation_policy_wanFirewall_removeSection/README.md +8 -6
  123. catocli/parsers/mutation_policy_wanFirewall_updatePolicy/README.md +8 -6
  124. catocli/parsers/mutation_policy_wanFirewall_updateRule/README.md +8 -6
  125. catocli/parsers/mutation_policy_wanFirewall_updateSection/README.md +8 -6
  126. catocli/parsers/mutation_policy_wanNetwork_addRule/README.md +8 -6
  127. catocli/parsers/mutation_policy_wanNetwork_addSection/README.md +8 -6
  128. catocli/parsers/mutation_policy_wanNetwork_createPolicyRevision/README.md +8 -6
  129. catocli/parsers/mutation_policy_wanNetwork_discardPolicyRevision/README.md +8 -6
  130. catocli/parsers/mutation_policy_wanNetwork_moveRule/README.md +8 -6
  131. catocli/parsers/mutation_policy_wanNetwork_moveSection/README.md +8 -6
  132. catocli/parsers/mutation_policy_wanNetwork_publishPolicyRevision/README.md +8 -6
  133. catocli/parsers/mutation_policy_wanNetwork_removeRule/README.md +8 -6
  134. catocli/parsers/mutation_policy_wanNetwork_removeSection/README.md +8 -6
  135. catocli/parsers/mutation_policy_wanNetwork_updatePolicy/README.md +8 -6
  136. catocli/parsers/mutation_policy_wanNetwork_updateRule/README.md +8 -6
  137. catocli/parsers/mutation_policy_wanNetwork_updateSection/README.md +8 -6
  138. catocli/parsers/mutation_sandbox/__init__.py +27 -27
  139. catocli/parsers/mutation_sandbox_deleteReport/README.md +7 -5
  140. catocli/parsers/mutation_sandbox_uploadFile/README.md +7 -5
  141. catocli/parsers/mutation_site/__init__.py +474 -474
  142. catocli/parsers/mutation_site_addBgpPeer/README.md +7 -5
  143. catocli/parsers/mutation_site_addCloudInterconnectPhysicalConnection/README.md +7 -5
  144. catocli/parsers/mutation_site_addCloudInterconnectSite/README.md +7 -5
  145. catocli/parsers/mutation_site_addIpsecIkeV2Site/README.md +7 -5
  146. catocli/parsers/mutation_site_addIpsecIkeV2SiteTunnels/README.md +8 -6
  147. catocli/parsers/mutation_site_addNetworkRange/README.md +8 -6
  148. catocli/parsers/mutation_site_addSecondaryAwsVSocket/README.md +7 -5
  149. catocli/parsers/mutation_site_addSecondaryAzureVSocket/README.md +7 -5
  150. catocli/parsers/mutation_site_addSocketAddOnCard/README.md +7 -5
  151. catocli/parsers/mutation_site_addSocketSite/README.md +7 -5
  152. catocli/parsers/mutation_site_addStaticHost/README.md +8 -6
  153. catocli/parsers/mutation_site_assignSiteBwLicense/README.md +7 -5
  154. catocli/parsers/mutation_site_removeBgpPeer/README.md +7 -5
  155. catocli/parsers/mutation_site_removeCloudInterconnectPhysicalConnection/README.md +7 -5
  156. catocli/parsers/mutation_site_removeIpsecIkeV2SiteTunnels/README.md +8 -6
  157. catocli/parsers/mutation_site_removeNetworkRange/README.md +7 -5
  158. catocli/parsers/mutation_site_removeSecondaryAwsVSocket/README.md +7 -5
  159. catocli/parsers/mutation_site_removeSecondaryAzureVSocket/README.md +7 -5
  160. catocli/parsers/mutation_site_removeSite/README.md +7 -5
  161. catocli/parsers/mutation_site_removeSiteBwLicense/README.md +7 -5
  162. catocli/parsers/mutation_site_removeSocketAddOnCard/README.md +7 -5
  163. catocli/parsers/mutation_site_removeStaticHost/README.md +7 -5
  164. catocli/parsers/mutation_site_replaceSiteBwLicense/README.md +7 -5
  165. catocli/parsers/mutation_site_startSiteUpgrade/README.md +7 -5
  166. catocli/parsers/mutation_site_updateBgpPeer/README.md +7 -5
  167. catocli/parsers/mutation_site_updateCloudInterconnectPhysicalConnection/README.md +7 -5
  168. catocli/parsers/mutation_site_updateHa/README.md +8 -6
  169. catocli/parsers/mutation_site_updateIpsecIkeV2SiteGeneralDetails/README.md +8 -6
  170. catocli/parsers/mutation_site_updateIpsecIkeV2SiteTunnels/README.md +8 -6
  171. catocli/parsers/mutation_site_updateNetworkRange/README.md +8 -6
  172. catocli/parsers/mutation_site_updateSecondaryAwsVSocket/README.md +7 -5
  173. catocli/parsers/mutation_site_updateSecondaryAzureVSocket/README.md +7 -5
  174. catocli/parsers/mutation_site_updateSiteBwLicense/README.md +7 -5
  175. catocli/parsers/mutation_site_updateSiteGeneralDetails/README.md +8 -6
  176. catocli/parsers/mutation_site_updateSocketInterface/README.md +9 -7
  177. catocli/parsers/mutation_site_updateStaticHost/README.md +8 -6
  178. catocli/parsers/mutation_sites/__init__.py +474 -474
  179. catocli/parsers/mutation_sites_addBgpPeer/README.md +7 -5
  180. catocli/parsers/mutation_sites_addCloudInterconnectPhysicalConnection/README.md +7 -5
  181. catocli/parsers/mutation_sites_addCloudInterconnectSite/README.md +7 -5
  182. catocli/parsers/mutation_sites_addIpsecIkeV2Site/README.md +7 -5
  183. catocli/parsers/mutation_sites_addIpsecIkeV2SiteTunnels/README.md +8 -6
  184. catocli/parsers/mutation_sites_addNetworkRange/README.md +8 -6
  185. catocli/parsers/mutation_sites_addSecondaryAwsVSocket/README.md +7 -5
  186. catocli/parsers/mutation_sites_addSecondaryAzureVSocket/README.md +7 -5
  187. catocli/parsers/mutation_sites_addSocketAddOnCard/README.md +7 -5
  188. catocli/parsers/mutation_sites_addSocketSite/README.md +7 -5
  189. catocli/parsers/mutation_sites_addStaticHost/README.md +8 -6
  190. catocli/parsers/mutation_sites_assignSiteBwLicense/README.md +7 -5
  191. catocli/parsers/mutation_sites_removeBgpPeer/README.md +7 -5
  192. catocli/parsers/mutation_sites_removeCloudInterconnectPhysicalConnection/README.md +7 -5
  193. catocli/parsers/mutation_sites_removeIpsecIkeV2SiteTunnels/README.md +8 -6
  194. catocli/parsers/mutation_sites_removeNetworkRange/README.md +7 -5
  195. catocli/parsers/mutation_sites_removeSecondaryAwsVSocket/README.md +7 -5
  196. catocli/parsers/mutation_sites_removeSecondaryAzureVSocket/README.md +7 -5
  197. catocli/parsers/mutation_sites_removeSite/README.md +7 -5
  198. catocli/parsers/mutation_sites_removeSiteBwLicense/README.md +7 -5
  199. catocli/parsers/mutation_sites_removeSocketAddOnCard/README.md +7 -5
  200. catocli/parsers/mutation_sites_removeStaticHost/README.md +7 -5
  201. catocli/parsers/mutation_sites_replaceSiteBwLicense/README.md +7 -5
  202. catocli/parsers/mutation_sites_startSiteUpgrade/README.md +7 -5
  203. catocli/parsers/mutation_sites_updateBgpPeer/README.md +7 -5
  204. catocli/parsers/mutation_sites_updateCloudInterconnectPhysicalConnection/README.md +7 -5
  205. catocli/parsers/mutation_sites_updateHa/README.md +8 -6
  206. catocli/parsers/mutation_sites_updateIpsecIkeV2SiteGeneralDetails/README.md +8 -6
  207. catocli/parsers/mutation_sites_updateIpsecIkeV2SiteTunnels/README.md +8 -6
  208. catocli/parsers/mutation_sites_updateNetworkRange/README.md +8 -6
  209. catocli/parsers/mutation_sites_updateSecondaryAwsVSocket/README.md +7 -5
  210. catocli/parsers/mutation_sites_updateSecondaryAzureVSocket/README.md +7 -5
  211. catocli/parsers/mutation_sites_updateSiteBwLicense/README.md +7 -5
  212. catocli/parsers/mutation_sites_updateSiteGeneralDetails/README.md +8 -6
  213. catocli/parsers/mutation_sites_updateSocketInterface/README.md +9 -7
  214. catocli/parsers/mutation_sites_updateStaticHost/README.md +8 -6
  215. catocli/parsers/mutation_xdr/__init__.py +45 -45
  216. catocli/parsers/mutation_xdr_addStoryComment/README.md +7 -5
  217. catocli/parsers/mutation_xdr_analystFeedback/README.md +7 -6
  218. catocli/parsers/mutation_xdr_deleteStoryComment/README.md +7 -5
  219. catocli/parsers/query_accountBySubdomain/README.md +7 -5
  220. catocli/parsers/query_accountBySubdomain/__init__.py +12 -12
  221. catocli/parsers/query_accountManagement/README.md +4 -5
  222. catocli/parsers/query_accountManagement/__init__.py +12 -12
  223. catocli/parsers/query_accountMetrics/README.md +20 -18
  224. catocli/parsers/query_accountMetrics/__init__.py +12 -12
  225. catocli/parsers/query_accountRoles/README.md +7 -5
  226. catocli/parsers/query_accountRoles/__init__.py +12 -12
  227. catocli/parsers/query_accountSnapshot/README.md +8 -6
  228. catocli/parsers/query_accountSnapshot/__init__.py +12 -12
  229. catocli/parsers/query_admin/README.md +7 -5
  230. catocli/parsers/query_admin/__init__.py +12 -12
  231. catocli/parsers/query_admins/README.md +11 -9
  232. catocli/parsers/query_admins/__init__.py +12 -12
  233. catocli/parsers/query_appStats/README.md +20 -11
  234. catocli/parsers/query_appStats/__init__.py +12 -12
  235. catocli/parsers/query_appStatsTimeSeries/README.md +21 -12
  236. catocli/parsers/query_appStatsTimeSeries/__init__.py +12 -12
  237. catocli/parsers/query_auditFeed/README.md +10 -8
  238. catocli/parsers/query_auditFeed/__init__.py +12 -12
  239. catocli/parsers/query_catalogs/README.md +9 -7
  240. catocli/parsers/query_catalogs/__init__.py +12 -12
  241. catocli/parsers/query_container/README.md +13 -11
  242. catocli/parsers/query_container/__init__.py +12 -12
  243. catocli/parsers/query_devices/README.md +10 -8
  244. catocli/parsers/query_devices/__init__.py +12 -12
  245. catocli/parsers/query_enterpriseDirectory/README.md +19 -0
  246. catocli/parsers/query_enterpriseDirectory/__init__.py +16 -0
  247. catocli/parsers/query_entityLookup/README.md +19 -17
  248. catocli/parsers/query_entityLookup/__init__.py +12 -12
  249. catocli/parsers/query_events/README.md +13 -11
  250. catocli/parsers/query_events/__init__.py +12 -12
  251. catocli/parsers/query_eventsFeed/README.md +9 -7
  252. catocli/parsers/query_eventsFeed/__init__.py +12 -12
  253. catocli/parsers/query_eventsTimeSeries/README.md +14 -12
  254. catocli/parsers/query_eventsTimeSeries/__init__.py +12 -12
  255. catocli/parsers/query_groups/__init__.py +51 -51
  256. catocli/parsers/query_groups_groupList/README.md +8 -6
  257. catocli/parsers/query_groups_group_members/README.md +8 -6
  258. catocli/parsers/query_groups_whereUsed/README.md +7 -5
  259. catocli/parsers/query_hardware/README.md +7 -5
  260. catocli/parsers/query_hardware/__init__.py +12 -12
  261. catocli/parsers/query_hardwareManagement/README.md +7 -5
  262. catocli/parsers/query_hardwareManagement/__init__.py +12 -12
  263. catocli/parsers/query_licensing/README.md +4 -5
  264. catocli/parsers/query_licensing/__init__.py +12 -12
  265. catocli/parsers/query_policy/__init__.py +158 -158
  266. catocli/parsers/query_policy_appTenantRestriction_policy/README.md +7 -5
  267. catocli/parsers/query_policy_dynamicIpAllocation_policy/README.md +7 -5
  268. catocli/parsers/query_policy_internetFirewall_policy/README.md +7 -5
  269. catocli/parsers/query_policy_remotePortFwd_policy/README.md +7 -5
  270. catocli/parsers/query_policy_socketLan_policy/README.md +7 -5
  271. catocli/parsers/query_policy_terminalServer_policy/README.md +7 -5
  272. catocli/parsers/query_policy_wanFirewall_policy/README.md +7 -5
  273. catocli/parsers/query_policy_wanNetwork_policy/README.md +7 -5
  274. catocli/parsers/query_popLocations/README.md +7 -5
  275. catocli/parsers/query_popLocations/__init__.py +12 -12
  276. catocli/parsers/query_sandbox/README.md +7 -5
  277. catocli/parsers/query_sandbox/__init__.py +12 -12
  278. catocli/parsers/query_servicePrincipalAdmin/README.md +19 -0
  279. catocli/parsers/query_servicePrincipalAdmin/__init__.py +16 -0
  280. catocli/parsers/query_site/__init__.py +123 -123
  281. catocli/parsers/query_siteLocation/__init__.py +10 -10
  282. catocli/parsers/query_site_availableVersionList/README.md +7 -5
  283. catocli/parsers/query_site_bgpPeer/README.md +7 -5
  284. catocli/parsers/query_site_bgpPeerList/README.md +7 -5
  285. catocli/parsers/query_site_cloudInterconnectConnectionConnectivity/README.md +7 -5
  286. catocli/parsers/query_site_cloudInterconnectPhysicalConnection/README.md +7 -5
  287. catocli/parsers/query_site_cloudInterconnectPhysicalConnectionId/README.md +7 -5
  288. catocli/parsers/query_site_secondaryAwsVSocket/README.md +7 -5
  289. catocli/parsers/query_site_secondaryAzureVSocket/README.md +7 -5
  290. catocli/parsers/query_site_siteBgpStatus/README.md +7 -5
  291. catocli/parsers/query_socketPortMetrics/README.md +13 -11
  292. catocli/parsers/query_socketPortMetrics/__init__.py +12 -12
  293. catocli/parsers/query_socketPortMetricsTimeSeries/README.md +14 -12
  294. catocli/parsers/query_socketPortMetricsTimeSeries/__init__.py +12 -12
  295. catocli/parsers/query_subDomains/README.md +7 -5
  296. catocli/parsers/query_subDomains/__init__.py +12 -12
  297. catocli/parsers/query_xdr/__init__.py +27 -27
  298. catocli/parsers/query_xdr_stories/README.md +7 -6
  299. catocli/parsers/query_xdr_story/README.md +9 -8
  300. catocli/parsers/raw/__init__.py +9 -9
  301. {catocli-2.1.1.dist-info → catocli-2.1.3.dist-info}/METADATA +1 -1
  302. catocli-2.1.3.dist-info/RECORD +660 -0
  303. models/mutation.accountManagement.addAccount.json +5 -15
  304. models/mutation.accountManagement.updateAccount.json +1 -3
  305. models/mutation.admin.addAdmin.json +14 -35
  306. models/mutation.admin.addServicePrincipalAdmin.json +2554 -0
  307. models/mutation.admin.removeAdmin.json +1 -1
  308. models/mutation.admin.removeServicePrincipalAdmin.json +201 -0
  309. models/mutation.admin.updateAdmin.json +13 -30
  310. models/mutation.admin.updateServicePrincipalAdmin.json +2554 -0
  311. models/mutation.container.delete.json +9 -435
  312. models/mutation.container.fqdn.addValues.json +6 -11
  313. models/mutation.container.fqdn.createFromFile.json +4 -12
  314. models/mutation.container.fqdn.removeValues.json +6 -11
  315. models/mutation.container.fqdn.updateFromFile.json +5 -15
  316. models/mutation.container.ipAddressRange.addValues.json +4 -12
  317. models/mutation.container.ipAddressRange.createFromFile.json +4 -12
  318. models/mutation.container.ipAddressRange.removeValues.json +4 -12
  319. models/mutation.container.ipAddressRange.updateFromFile.json +5 -15
  320. models/mutation.enterpriseDirectory.archiveLocation.json +1046 -0
  321. models/mutation.enterpriseDirectory.createLocation.json +2521 -0
  322. models/mutation.enterpriseDirectory.restoreLocation.json +1046 -0
  323. models/mutation.enterpriseDirectory.updateLocation.json +2567 -0
  324. models/mutation.groups.createGroup.json +39 -171
  325. models/mutation.groups.deleteGroup.json +36 -162
  326. models/mutation.groups.updateGroup.json +41 -177
  327. models/mutation.hardware.updateHardwareShipping.json +18 -47
  328. models/mutation.policy.appTenantRestriction.addRule.json +50 -136
  329. models/mutation.policy.appTenantRestriction.addSection.json +4 -12
  330. models/mutation.policy.appTenantRestriction.createPolicyRevision.json +3 -9
  331. models/mutation.policy.appTenantRestriction.discardPolicyRevision.json +2 -6
  332. models/mutation.policy.appTenantRestriction.moveRule.json +4 -12
  333. models/mutation.policy.appTenantRestriction.moveSection.json +4 -12
  334. models/mutation.policy.appTenantRestriction.publishPolicyRevision.json +3 -9
  335. models/mutation.policy.appTenantRestriction.removeRule.json +2 -6
  336. models/mutation.policy.appTenantRestriction.removeSection.json +2 -6
  337. models/mutation.policy.appTenantRestriction.updatePolicy.json +2 -6
  338. models/mutation.policy.appTenantRestriction.updateRule.json +49 -133
  339. models/mutation.policy.appTenantRestriction.updateSection.json +3 -9
  340. models/mutation.policy.dynamicIpAllocation.addRule.json +15 -45
  341. models/mutation.policy.dynamicIpAllocation.addSection.json +4 -12
  342. models/mutation.policy.dynamicIpAllocation.createPolicyRevision.json +3 -9
  343. models/mutation.policy.dynamicIpAllocation.discardPolicyRevision.json +2 -6
  344. models/mutation.policy.dynamicIpAllocation.moveRule.json +4 -12
  345. models/mutation.policy.dynamicIpAllocation.moveSection.json +4 -12
  346. models/mutation.policy.dynamicIpAllocation.publishPolicyRevision.json +3 -9
  347. models/mutation.policy.dynamicIpAllocation.removeRule.json +2 -6
  348. models/mutation.policy.dynamicIpAllocation.removeSection.json +2 -6
  349. models/mutation.policy.dynamicIpAllocation.updatePolicy.json +2 -6
  350. models/mutation.policy.dynamicIpAllocation.updateRule.json +14 -42
  351. models/mutation.policy.dynamicIpAllocation.updateSection.json +3 -9
  352. models/mutation.policy.internetFirewall.addRule.json +248 -542
  353. models/mutation.policy.internetFirewall.addSection.json +4 -12
  354. models/mutation.policy.internetFirewall.createPolicyRevision.json +3 -9
  355. models/mutation.policy.internetFirewall.discardPolicyRevision.json +2 -6
  356. models/mutation.policy.internetFirewall.moveRule.json +4 -12
  357. models/mutation.policy.internetFirewall.moveSection.json +4 -12
  358. models/mutation.policy.internetFirewall.publishPolicyRevision.json +3 -9
  359. models/mutation.policy.internetFirewall.removeRule.json +2 -6
  360. models/mutation.policy.internetFirewall.removeSection.json +2 -6
  361. models/mutation.policy.internetFirewall.updatePolicy.json +2 -6
  362. models/mutation.policy.internetFirewall.updateRule.json +247 -539
  363. models/mutation.policy.internetFirewall.updateSection.json +3 -9
  364. models/mutation.policy.remotePortFwd.addRule.json +35 -91
  365. models/mutation.policy.remotePortFwd.addSection.json +4 -12
  366. models/mutation.policy.remotePortFwd.createPolicyRevision.json +3 -9
  367. models/mutation.policy.remotePortFwd.discardPolicyRevision.json +2 -6
  368. models/mutation.policy.remotePortFwd.moveRule.json +4 -12
  369. models/mutation.policy.remotePortFwd.moveSection.json +4 -12
  370. models/mutation.policy.remotePortFwd.publishPolicyRevision.json +3 -9
  371. models/mutation.policy.remotePortFwd.removeRule.json +2 -6
  372. models/mutation.policy.remotePortFwd.removeSection.json +2 -6
  373. models/mutation.policy.remotePortFwd.updatePolicy.json +2 -6
  374. models/mutation.policy.remotePortFwd.updateRule.json +34 -88
  375. models/mutation.policy.remotePortFwd.updateSection.json +3 -9
  376. models/mutation.policy.socketLan.addRule.json +78 -185
  377. models/mutation.policy.socketLan.addSection.json +4 -12
  378. models/mutation.policy.socketLan.createPolicyRevision.json +3 -9
  379. models/mutation.policy.socketLan.discardPolicyRevision.json +2 -6
  380. models/mutation.policy.socketLan.moveRule.json +4 -12
  381. models/mutation.policy.socketLan.moveSection.json +4 -12
  382. models/mutation.policy.socketLan.publishPolicyRevision.json +3 -9
  383. models/mutation.policy.socketLan.removeRule.json +2 -6
  384. models/mutation.policy.socketLan.removeSection.json +2 -6
  385. models/mutation.policy.socketLan.updatePolicy.json +2 -6
  386. models/mutation.policy.socketLan.updateRule.json +77 -182
  387. models/mutation.policy.socketLan.updateSection.json +3 -9
  388. models/mutation.policy.terminalServer.addRule.json +10 -30
  389. models/mutation.policy.terminalServer.addSection.json +4 -12
  390. models/mutation.policy.terminalServer.createPolicyRevision.json +3 -9
  391. models/mutation.policy.terminalServer.discardPolicyRevision.json +2 -6
  392. models/mutation.policy.terminalServer.moveRule.json +4 -12
  393. models/mutation.policy.terminalServer.moveSection.json +4 -12
  394. models/mutation.policy.terminalServer.publishPolicyRevision.json +3 -9
  395. models/mutation.policy.terminalServer.removeRule.json +2 -6
  396. models/mutation.policy.terminalServer.removeSection.json +2 -6
  397. models/mutation.policy.terminalServer.updatePolicy.json +2 -6
  398. models/mutation.policy.terminalServer.updateRule.json +9 -27
  399. models/mutation.policy.terminalServer.updateSection.json +3 -9
  400. models/mutation.policy.wanFirewall.addRule.json +290 -654
  401. models/mutation.policy.wanFirewall.addSection.json +4 -12
  402. models/mutation.policy.wanFirewall.createPolicyRevision.json +3 -9
  403. models/mutation.policy.wanFirewall.discardPolicyRevision.json +2 -6
  404. models/mutation.policy.wanFirewall.moveRule.json +4 -12
  405. models/mutation.policy.wanFirewall.moveSection.json +4 -12
  406. models/mutation.policy.wanFirewall.publishPolicyRevision.json +3 -9
  407. models/mutation.policy.wanFirewall.removeRule.json +2 -6
  408. models/mutation.policy.wanFirewall.removeSection.json +2 -6
  409. models/mutation.policy.wanFirewall.updatePolicy.json +2 -6
  410. models/mutation.policy.wanFirewall.updateRule.json +289 -651
  411. models/mutation.policy.wanFirewall.updateSection.json +3 -9
  412. models/mutation.policy.wanNetwork.addRule.json +204 -514
  413. models/mutation.policy.wanNetwork.addSection.json +4 -12
  414. models/mutation.policy.wanNetwork.createPolicyRevision.json +3 -9
  415. models/mutation.policy.wanNetwork.discardPolicyRevision.json +2 -6
  416. models/mutation.policy.wanNetwork.moveRule.json +4 -12
  417. models/mutation.policy.wanNetwork.moveSection.json +4 -12
  418. models/mutation.policy.wanNetwork.publishPolicyRevision.json +3 -9
  419. models/mutation.policy.wanNetwork.removeRule.json +2 -6
  420. models/mutation.policy.wanNetwork.removeSection.json +2 -6
  421. models/mutation.policy.wanNetwork.updatePolicy.json +2 -6
  422. models/mutation.policy.wanNetwork.updateRule.json +203 -511
  423. models/mutation.policy.wanNetwork.updateSection.json +3 -9
  424. models/mutation.sandbox.deleteReport.json +1 -3
  425. models/mutation.sandbox.uploadFile.json +1 -3
  426. models/mutation.site.addBgpPeer.json +48 -123
  427. models/mutation.site.addCloudInterconnectPhysicalConnection.json +12 -36
  428. models/mutation.site.addCloudInterconnectSite.json +8 -24
  429. models/mutation.site.addIpsecIkeV2Site.json +10 -30
  430. models/mutation.site.addIpsecIkeV2SiteTunnels.json +14 -40
  431. models/mutation.site.addNetworkRange.json +15 -43
  432. models/mutation.site.addSecondaryAwsVSocket.json +5 -15
  433. models/mutation.site.addSecondaryAzureVSocket.json +4 -12
  434. models/mutation.site.addSocketAddOnCard.json +4 -12
  435. models/mutation.site.addSocketSite.json +12 -36
  436. models/mutation.site.addStaticHost.json +4 -10
  437. models/mutation.site.assignSiteBwLicense.json +120 -11782
  438. models/mutation.site.removeBgpPeer.json +1 -3
  439. models/mutation.site.removeCloudInterconnectPhysicalConnection.json +1 -3
  440. models/mutation.site.removeIpsecIkeV2SiteTunnels.json +2 -4
  441. models/mutation.site.removeNetworkRange.json +1 -1
  442. models/mutation.site.removeSecondaryAwsVSocket.json +1 -1
  443. models/mutation.site.removeSecondaryAzureVSocket.json +1 -1
  444. models/mutation.site.removeSite.json +1 -1
  445. models/mutation.site.removeSiteBwLicense.json +119 -11779
  446. models/mutation.site.removeSocketAddOnCard.json +3 -9
  447. models/mutation.site.removeStaticHost.json +1 -1
  448. models/mutation.site.replaceSiteBwLicense.json +121 -11785
  449. models/mutation.site.startSiteUpgrade.json +3 -9
  450. models/mutation.site.updateBgpPeer.json +47 -120
  451. models/mutation.site.updateCloudInterconnectPhysicalConnection.json +10 -30
  452. models/mutation.site.updateHa.json +4 -10
  453. models/mutation.site.updateIpsecIkeV2SiteGeneralDetails.json +11 -24
  454. models/mutation.site.updateIpsecIkeV2SiteTunnels.json +15 -43
  455. models/mutation.site.updateNetworkRange.json +15 -43
  456. models/mutation.site.updateSecondaryAwsVSocket.json +4 -12
  457. models/mutation.site.updateSecondaryAzureVSocket.json +3 -9
  458. models/mutation.site.updateSiteBwLicense.json +120 -11782
  459. models/mutation.site.updateSiteGeneralDetails.json +14 -40
  460. models/mutation.site.updateSocketInterface.json +26 -74
  461. models/mutation.site.updateStaticHost.json +4 -10
  462. models/mutation.sites.addBgpPeer.json +48 -123
  463. models/mutation.sites.addCloudInterconnectPhysicalConnection.json +12 -36
  464. models/mutation.sites.addCloudInterconnectSite.json +8 -24
  465. models/mutation.sites.addIpsecIkeV2Site.json +10 -30
  466. models/mutation.sites.addIpsecIkeV2SiteTunnels.json +14 -40
  467. models/mutation.sites.addNetworkRange.json +15 -43
  468. models/mutation.sites.addSecondaryAwsVSocket.json +5 -15
  469. models/mutation.sites.addSecondaryAzureVSocket.json +4 -12
  470. models/mutation.sites.addSocketAddOnCard.json +4 -12
  471. models/mutation.sites.addSocketSite.json +12 -36
  472. models/mutation.sites.addStaticHost.json +4 -10
  473. models/mutation.sites.assignSiteBwLicense.json +120 -11782
  474. models/mutation.sites.removeBgpPeer.json +1 -3
  475. models/mutation.sites.removeCloudInterconnectPhysicalConnection.json +1 -3
  476. models/mutation.sites.removeIpsecIkeV2SiteTunnels.json +2 -4
  477. models/mutation.sites.removeNetworkRange.json +1 -1
  478. models/mutation.sites.removeSecondaryAwsVSocket.json +1 -1
  479. models/mutation.sites.removeSecondaryAzureVSocket.json +1 -1
  480. models/mutation.sites.removeSite.json +1 -1
  481. models/mutation.sites.removeSiteBwLicense.json +119 -11779
  482. models/mutation.sites.removeSocketAddOnCard.json +3 -9
  483. models/mutation.sites.removeStaticHost.json +1 -1
  484. models/mutation.sites.replaceSiteBwLicense.json +121 -11785
  485. models/mutation.sites.startSiteUpgrade.json +3 -9
  486. models/mutation.sites.updateBgpPeer.json +47 -120
  487. models/mutation.sites.updateCloudInterconnectPhysicalConnection.json +10 -30
  488. models/mutation.sites.updateHa.json +4 -10
  489. models/mutation.sites.updateIpsecIkeV2SiteGeneralDetails.json +11 -24
  490. models/mutation.sites.updateIpsecIkeV2SiteTunnels.json +15 -43
  491. models/mutation.sites.updateNetworkRange.json +15 -43
  492. models/mutation.sites.updateSecondaryAwsVSocket.json +4 -12
  493. models/mutation.sites.updateSecondaryAzureVSocket.json +3 -9
  494. models/mutation.sites.updateSiteBwLicense.json +120 -11782
  495. models/mutation.sites.updateSiteGeneralDetails.json +14 -40
  496. models/mutation.sites.updateSocketInterface.json +26 -74
  497. models/mutation.sites.updateStaticHost.json +4 -10
  498. models/mutation.xdr.addStoryComment.json +15 -113
  499. models/mutation.xdr.analystFeedback.json +229 -26307
  500. models/mutation.xdr.deleteStoryComment.json +15 -113
  501. models/query.accountBySubdomain.json +2 -1
  502. models/query.accountMetrics.json +15 -12
  503. models/query.accountRoles.json +1 -1
  504. models/query.accountSnapshot.json +4 -2
  505. models/query.admin.json +1 -1
  506. models/query.admins.json +7 -10
  507. models/query.appStats.json +633 -33
  508. models/query.appStatsTimeSeries.json +15 -28
  509. models/query.auditFeed.json +225 -16
  510. models/query.catalogs.json +106 -215
  511. models/query.container.json +21 -471
  512. models/query.devices.json +333 -620
  513. models/query.enterpriseDirectory.json +3596 -0
  514. models/query.entityLookup.json +15 -27
  515. models/query.events.json +1875 -33
  516. models/query.eventsFeed.json +30 -14
  517. models/query.eventsTimeSeries.json +15 -28
  518. models/query.groups.group.members.json +23 -55
  519. models/query.groups.groupList.json +87 -266
  520. models/query.groups.whereUsed.json +2 -6
  521. models/query.hardware.json +92 -192
  522. models/query.hardwareManagement.json +21 -63
  523. models/query.licensing.json +76 -11721
  524. models/query.policy.appTenantRestriction.policy.json +2 -6
  525. models/query.policy.dynamicIpAllocation.policy.json +2 -6
  526. models/query.policy.internetFirewall.policy.json +2 -6
  527. models/query.policy.remotePortFwd.policy.json +2 -6
  528. models/query.policy.socketLan.policy.json +2 -6
  529. models/query.policy.terminalServer.policy.json +2 -6
  530. models/query.policy.wanFirewall.policy.json +2 -6
  531. models/query.policy.wanNetwork.policy.json +2 -6
  532. models/query.popLocations.json +34 -74
  533. models/query.sandbox.json +44 -83
  534. models/query.servicePrincipalAdmin.json +1098 -0
  535. models/query.site.availableVersionList.json +4 -5
  536. models/query.site.bgpPeer.json +2 -6
  537. models/query.site.bgpPeerList.json +2 -6
  538. models/query.site.cloudInterconnectConnectionConnectivity.json +1 -3
  539. models/query.site.cloudInterconnectPhysicalConnection.json +1 -3
  540. models/query.site.cloudInterconnectPhysicalConnectionId.json +3 -9
  541. models/query.site.secondaryAwsVSocket.json +1 -1
  542. models/query.site.secondaryAzureVSocket.json +1 -1
  543. models/query.site.siteBgpStatus.json +2 -6
  544. models/query.socketPortMetrics.json +465 -33
  545. models/query.socketPortMetricsTimeSeries.json +15 -28
  546. models/query.subDomains.json +1 -1
  547. models/query.xdr.stories.json +306 -26440
  548. models/query.xdr.story.json +40 -26100
  549. schema/catolib.py +1255 -972
  550. schema/importSchema.py +53 -48
  551. catocli/parsers/mutation/README.md +0 -4
  552. catocli/parsers/mutation_accountManagement_disableAccount/README.md +0 -16
  553. catocli/parsers/parserApiClient.py +0 -948
  554. catocli/parsers/query/README.md +0 -3
  555. catocli-2.1.1.dist-info/RECORD +0 -645
  556. models/mutation.accountManagement.disableAccount.json +0 -545
  557. models/query.policy.json +0 -40899
  558. models/query.site.json +0 -5688
  559. schema/remove_policyid.py +0 -89
  560. schema/remove_policyid_mutations.py +0 -89
  561. {catocli-2.1.1.dist-info → catocli-2.1.3.dist-info}/WHEEL +0 -0
  562. {catocli-2.1.1.dist-info → catocli-2.1.3.dist-info}/entry_points.txt +0 -0
  563. {catocli-2.1.1.dist-info → catocli-2.1.3.dist-info}/licenses/LICENSE +0 -0
  564. {catocli-2.1.1.dist-info → catocli-2.1.3.dist-info}/top_level.txt +0 -0
@@ -1,948 +0,0 @@
1
- import codecs
2
- import json
3
- import os
4
- import sys
5
- from graphql_client import ApiClient, CallApi
6
- from graphql_client.api_client import ApiException
7
- import logging
8
- import pprint
9
- import uuid
10
- import string
11
- from urllib3.filepost import encode_multipart_formdata
12
-
13
- def createRequest(args, configuration):
14
- params = vars(args)
15
- instance = CallApi(ApiClient(configuration))
16
- operationName = params["operation_name"]
17
- operation = loadJSON("models/"+operationName+".json")
18
- variablesObj = {}
19
- if params["json"] and not params["t"]:
20
- try:
21
- variablesObj = json.loads(params["json"])
22
- except ValueError as e:
23
- print("ERROR: Query argument must be valid json in quotes. ",e,'\n\nExample: \'{"yourKey":"yourValue"}\'')
24
- exit()
25
- elif not params["t"] and params["json"] is None:
26
- # Default to empty object if no json provided and not using -t flag
27
- variablesObj = {}
28
- # Special handling for eventsFeed and auditFeed which use accountIDs array
29
- if operationName in ["query.eventsFeed", "query.auditFeed"]:
30
- # Only add accountIDs if not already provided in JSON
31
- if "accountIDs" not in variablesObj:
32
- variablesObj["accountIDs"] = [configuration.accountID]
33
- elif "accountId" in operation["args"]:
34
- variablesObj["accountId"] = configuration.accountID
35
- else:
36
- variablesObj["accountID"] = configuration.accountID
37
- if params["t"]==True:
38
- # Skip validation when using -t flag
39
- isOk = True
40
- else:
41
- isOk, invalidVars, message = validateArgs(variablesObj,operation)
42
- if isOk==True:
43
- body = generateGraphqlPayload(variablesObj,operation,operationName)
44
- if params["t"]==True:
45
- # Load query from queryPayloads file
46
- try:
47
- queryPayloadFile = "queryPayloads/" + operationName + ".json"
48
- queryPayload = loadJSON(queryPayloadFile)
49
- if queryPayload and "query" in queryPayload:
50
- print(queryPayload["query"])
51
- else:
52
- print("ERROR: Query not found in " + queryPayloadFile)
53
- except Exception as e:
54
- print("ERROR: Could not load query from " + queryPayloadFile + ": " + str(e))
55
- return None
56
- else:
57
- try:
58
- return instance.call_api(body,params)
59
- except ApiException as e:
60
- return e
61
- else:
62
- print("ERROR: "+message,", ".join(invalidVars))
63
- try:
64
- queryPayloadFile = "queryPayloads/" + operationName + ".json"
65
- queryPayload = loadJSON(queryPayloadFile)
66
- print("\nExample: catocli "+operationName.replace(".", " "), json.dumps(queryPayload['variables']))
67
- except Exception as e:
68
- print("ERROR: Could not load query from " + queryPayloadFile + ": " + str(e))
69
-
70
- def querySiteLocation(args, configuration):
71
- params = vars(args)
72
- operationName = params["operation_name"]
73
- operation = loadJSON("models/"+operationName+".json")
74
- try:
75
- variablesObj = json.loads(params["json"])
76
- except ValueError as e:
77
- print("ERROR: Query argument must be valid json in quotes. ",e,'\n\nExample: \'{"filters":[{"search": "Your city here","field":"city","opeation":"exact"}}\'')
78
- exit()
79
- if not variablesObj.get("filters"):
80
- print("ERROR: Missing argument, must include filters array. ",e,'\n\nExample: \'{"filters":[{"search": "Your city here","field":"city","opeation":"exact"}}\'')
81
- exit()
82
- if not isinstance(variablesObj.get("filters"), list):
83
- print("ERROR: Invalid argument, must include filters array. ",e,'\n\nExample: \'{"filters":[{"search": "Your city here","field":"city","opeation":"exact"}}\'')
84
- exit()
85
- requiredFields = ["search","field","operation"]
86
- for filter in variablesObj["filters"]:
87
- if not isinstance(filter, dict):
88
- print("ERROR: Invalid filter '"+str(filter)+"', filters must be valid json and include 'search', 'field', and 'operation'. ",'\n\nExample: \'{"filters":[{"search": "Your city here","field":"city","opeation":"exact"}}\'',type(filter))
89
- exit()
90
- for param in filter:
91
- if param not in requiredFields:
92
- print("ERROR: Invalid field '"+param+"', filters must include 'search', 'field', and 'operation'. ",'\n\nExample: \'{"filters":[{"search": "Your city here","field":"city","opeation":"exact"}}\'')
93
- exit()
94
- for filter in variablesObj["filters"]:
95
- for param in filter:
96
- val = filter.get(param)
97
- if param=="search" and (not isinstance(val, str) or len(val)<3):
98
- print("ERROR: Invalid search '"+val+"', must be a string value and at least 3 characters in lengh. ",'\n\nExample: \'{"filters":[{"search": "Your city here","field":"city","opeation":"exact"}}\'')
99
- exit()
100
- if param=="field" and (not isinstance(val, str) or val not in [ 'countryName', 'stateName', 'city']):
101
- print("ERROR: Invalid field '"+val+"', must be one of the following: 'countryName', 'stateName', or 'city'.",'\n\nExample: \'{"search":"your query here","field":"city"}\'')
102
- exit()
103
- if param=="operation" and (not isinstance(val, str) or val not in [ 'startsWith', 'endsWith', 'exact', 'contains' ]):
104
- print("ERROR: Invalid operation '"+val+"', must be one of the following: 'startsWith', 'endsWith', 'exact', 'contains'.",'\n\nExample: \'{"search": "Your search here","field":"city","operation":"exact"}\'')
105
- exit()
106
- response = {"data":[]}
107
- for key, siteObj in operation.items():
108
- isOk = True
109
- for filter in variablesObj["filters"]:
110
- search = filter.get("search")
111
- field = filter.get("field")
112
- operation = filter.get("operation")
113
- if field in siteObj:
114
- if operation=="startsWith" and not siteObj[field].startswith(search):
115
- isOk = False
116
- break
117
- elif operation=="endsWith" and not siteObj[field].endswith(search):
118
- isOk = False
119
- break
120
- elif operation=="exact" and not siteObj[field]==search:
121
- isOk = False
122
- break
123
- elif operation=="contains" and not search in siteObj[field]:
124
- isOk = False
125
- break
126
- else:
127
- isOk = False
128
- break
129
- if isOk==False:
130
- break
131
- if isOk==True:
132
- response["data"].append(siteObj)
133
- if params["p"]==True:
134
- responseStr = json.dumps(response,indent=2,sort_keys=True,ensure_ascii=False).encode('utf8')
135
- print(responseStr.decode())
136
- else:
137
- responseStr = json.dumps(response,ensure_ascii=False).encode('utf8')
138
- print(responseStr.decode())
139
-
140
- def createRawRequest(args, configuration):
141
- params = vars(args)
142
- # Handle endpoint override
143
- if hasattr(args, 'endpoint') and args.endpoint:
144
- configuration.host = args.endpoint
145
-
146
- # Check if binary/multipart mode is enabled
147
- if hasattr(args, 'binary') and args.binary:
148
- return createRawBinaryRequest(args, configuration)
149
-
150
- instance = CallApi(ApiClient(configuration))
151
- isOk = False
152
- try:
153
- body = json.loads(params["json"])
154
- isOk = True
155
- except ValueError as e:
156
- print("ERROR: Argument must be valid json. ",e)
157
- isOk=False
158
- except Exception as e:
159
- isOk=False
160
- print("ERROR: ",e)
161
- if isOk==True:
162
- if params["t"]==True:
163
- if params["p"]==True:
164
- print(json.dumps(body,indent=2,sort_keys=True).replace("\\n", "\n").replace("\\t", "\t"))
165
- else:
166
- print(json.dumps(body).replace("\\n", " ").replace("\\t", " ").replace(" "," ").replace(" "," "))
167
- return None
168
- else:
169
- try:
170
- return instance.call_api(body,params)
171
- except ApiException as e:
172
- print(e)
173
- exit()
174
-
175
- def generateGraphqlPayload(variablesObj,operation,operationName):
176
- indent = " "
177
- queryStr = ""
178
- variableStr = ""
179
- for varName in variablesObj:
180
- if (varName in operation["operationArgs"]):
181
- variableStr += operation["operationArgs"][varName]["requestStr"]
182
- operationAry = operationName.split(".")
183
- operationType = operationAry.pop(0)
184
- queryStr = operationType + " "
185
- queryStr += renderCamelCase(".".join(operationAry))
186
- queryStr += " ( " + variableStr + ") {\n"
187
- queryStr += indent + operation["name"] + " ( "
188
- for argName in operation["args"]:
189
- arg = operation["args"][argName]
190
- if arg["varName"] in variablesObj:
191
- queryStr += arg["responseStr"]
192
- queryStr += ") {\n" + renderArgsAndFields("", variablesObj, operation, operation["type"]["definition"], " ") + " }"
193
- queryStr += indent + "\n}";
194
- body = {
195
- "query":queryStr,
196
- "variables":variablesObj,
197
- "operationName":renderCamelCase(".".join(operationAry)),
198
- }
199
- return body
200
-
201
- def get_help(path):
202
- matchCmd = "catocli "+path.replace("_"," ")
203
- import os
204
- pwd = os.path.dirname(__file__)
205
- doc = path+"/README.md"
206
- abs_path = os.path.join(pwd, doc)
207
- new_line = "\nEXAMPLES:\n"
208
- lines = open(abs_path, "r").readlines()
209
- for line in lines:
210
- if f"{matchCmd}" in line:
211
- clean_line = line.replace("<br /><br />", "").replace("`","")
212
- new_line += f"{clean_line}\n"
213
- # matchArg = path.replace("_",".")
214
- # for line in lines:
215
- # if f"`{matchArg}" in line:
216
- # clean_line = line.replace("<br /><br />", "").replace("`","")
217
- # new_line += f"{clean_line}\n"
218
- return new_line
219
-
220
- def validateArgs(variablesObj,operation):
221
- isOk = True
222
- invalidVars = []
223
- message = "Arguments are missing or have invalid values: "
224
- for varName in variablesObj:
225
- if varName not in operation["operationArgs"]:
226
- isOk = False
227
- invalidVars.append('"'+varName+'"')
228
- message = "Invalid argument names. Looking for: "+", ".join(list(operation["operationArgs"].keys()))
229
-
230
- if isOk==True:
231
- for varName in operation["operationArgs"]:
232
- if operation["operationArgs"][varName]["required"] and varName not in variablesObj:
233
- isOk = False
234
- invalidVars.append('"'+varName+'"')
235
- else:
236
- if varName in variablesObj:
237
- value = variablesObj[varName]
238
- if operation["operationArgs"][varName]["required"] and value=="":
239
- isOk = False
240
- invalidVars.append('"'+varName+'":"'+str(value)+'"')
241
- return isOk, invalidVars, message
242
-
243
- def loadJSON(file):
244
- CONFIG = {}
245
- module_dir = os.path.dirname(__file__)
246
- # Navigate up two directory levels (from parsers/ to catocli/ to root)
247
- module_dir = os.path.dirname(module_dir) # Go up from parsers/
248
- module_dir = os.path.dirname(module_dir) # Go up from catocli/
249
- try:
250
- file_path = os.path.join(module_dir, file)
251
- with open(file_path, 'r') as data:
252
- CONFIG = json.load(data)
253
- return CONFIG
254
- except:
255
- logging.warning(f"File \"{os.path.join(module_dir, file)}\" not found.")
256
- exit()
257
-
258
- def renderCamelCase(pathStr):
259
- str = ""
260
- pathAry = pathStr.split(".")
261
- for i, path in enumerate(pathAry):
262
- if i == 0:
263
- str += path[0].lower() + path[1:]
264
- else:
265
- str += path[0].upper() + path[1:]
266
- return str
267
-
268
- def renderArgsAndFields(responseArgStr, variablesObj, curOperation, definition, indent):
269
- for fieldName in definition['fields']:
270
- field = definition['fields'][fieldName]
271
- field_name = field['alias'] if 'alias' in field else field['name']
272
-
273
- # Check if field has arguments and whether they are present in variables
274
- should_include_field = True
275
- argsPresent = False
276
- argStr = ""
277
-
278
- if field.get("args") and not isinstance(field['args'], list):
279
- if (len(list(field['args'].keys()))>0):
280
- # Field has arguments - only include if arguments are present in variables
281
- argStr = " ( "
282
- for argName in field['args']:
283
- arg = field['args'][argName]
284
- if arg["varName"] in variablesObj:
285
- argStr += arg['responseStr'] + " "
286
- argsPresent = True
287
- argStr += ") "
288
- # Only include fields with arguments if the arguments are present
289
- should_include_field = argsPresent
290
-
291
- # Only process field if we should include it
292
- if should_include_field:
293
- responseArgStr += indent + field_name
294
- if argsPresent:
295
- responseArgStr += argStr
296
-
297
- if should_include_field and field.get("type") and field['type'].get('definition') and field['type']['definition']['fields'] is not None:
298
- responseArgStr += " {\n"
299
- for subfieldIndex in field['type']['definition']['fields']:
300
- subfield = field['type']['definition']['fields'][subfieldIndex]
301
- # Use the alias if it exists, otherwise use the field name
302
- subfield_name = subfield['alias'] if 'alias' in subfield else subfield['name']
303
- responseArgStr += indent + " " + subfield_name
304
- if subfield.get("args") and len(list(subfield["args"].keys()))>0:
305
- argsPresent = False
306
- subArgStr = " ( "
307
- for argName in subfield['args']:
308
- arg = subfield['args'][argName]
309
- if arg["varName"] in variablesObj:
310
- argsPresent = True
311
- subArgStr += arg['responseStr'] + " "
312
- subArgStr += " )"
313
- if argsPresent==True:
314
- responseArgStr += subArgStr
315
- if subfield.get("type") and subfield['type'].get("definition") and (subfield['type']['definition'].get("fields") or subfield['type']['definition'].get('inputFields')):
316
- responseArgStr += " {\n"
317
- responseArgStr = renderArgsAndFields(responseArgStr, variablesObj, curOperation, subfield['type']['definition'], indent + " ")
318
- if subfield['type']['definition'].get('possibleTypes'):
319
- for possibleTypeName in subfield['type']['definition']['possibleTypes']:
320
- possibleType = subfield['type']['definition']['possibleTypes'][possibleTypeName]
321
- responseArgStr += indent + " ... on " + possibleType['name'] + " {\n"
322
- if possibleType.get('fields') or possibleType.get('inputFields'):
323
- responseArgStr = renderArgsAndFields(responseArgStr, variablesObj, curOperation, possibleType, indent + " ")
324
- responseArgStr += indent + " }\n"
325
- responseArgStr += indent + " }"
326
- elif subfield.get('type') and subfield['type'].get('definition') and subfield['type']['definition'].get('possibleTypes'):
327
- responseArgStr += " {\n"
328
- responseArgStr += indent + " __typename\n"
329
- for possibleTypeName in subfield['type']['definition']['possibleTypes']:
330
- possibleType = subfield['type']['definition']['possibleTypes'][possibleTypeName]
331
- responseArgStr += indent + " ... on " + possibleType['name'] + " {\n"
332
- if possibleType.get('fields') or possibleType.get('inputFields'):
333
- responseArgStr = renderArgsAndFields(responseArgStr, variablesObj, curOperation, possibleType, indent + " ")
334
- responseArgStr += indent + " }\n"
335
- responseArgStr += indent + " }\n"
336
- responseArgStr += "\n"
337
- if field['type']['definition'].get('possibleTypes'):
338
- for possibleTypeName in field['type']['definition']['possibleTypes']:
339
- possibleType = field['type']['definition']['possibleTypes'][possibleTypeName]
340
- responseArgStr += indent + " ... on " + possibleType['name'] + " {\n"
341
- if possibleType.get('fields') or possibleType.get('inputFields'):
342
- responseArgStr = renderArgsAndFields(responseArgStr, variablesObj, curOperation, possibleType, indent + " ")
343
- responseArgStr += indent + " }\n"
344
- responseArgStr += indent + "}\n"
345
- if should_include_field and field.get('type') and field['type'].get('definition') and field['type']['definition'].get('inputFields'):
346
- responseArgStr += " {\n"
347
- for subfieldName in field['type']['definition'].get('inputFields'):
348
- subfield = field['type']['definition']['inputFields'][subfieldName]
349
- # Updated aliasing logic for inputFields
350
- if (subfield.get('type') and subfield['type'].get('name') and
351
- curOperation.get('fieldTypes', {}).get(subfield['type']['name']) and
352
- subfield.get('type', {}).get('kind') and
353
- 'SCALAR' not in str(subfield['type']['kind'])):
354
- subfield_name = f"{subfield['name']}{field['type']['definition']['name']}: {subfield['name']}"
355
- else:
356
- subfield_name = subfield['name'] # Always use the raw field name, not incorrect aliases
357
- responseArgStr += indent + " " + subfield_name
358
- if subfield.get('type') and subfield['type'].get('definition') and (subfield['type']['definition'].get('fields') or subfield['type']['definition'].get('inputFields')):
359
- responseArgStr += " {\n"
360
- responseArgStr = renderArgsAndFields(responseArgStr, variablesObj, curOperation, subfield['type']['definition'], indent + " ")
361
- responseArgStr += indent + " }\n"
362
- if field['type']['definition'].get('possibleTypes'):
363
- for possibleTypeName in field['type']['definition']['possibleTypes']:
364
- possibleType = field['type']['definition']['possibleTypes'][possibleTypeName]
365
- responseArgStr += indent + "... on " + possibleType['name'] + " {\n"
366
- if possibleType.get('fields') or possibleType.get('inputFields'):
367
- responseArgStr = renderArgsAndFields(responseArgStr, variablesObj, curOperation, possibleType, indent + " ")
368
- responseArgStr += indent + " }\n"
369
- responseArgStr += indent + "}\n"
370
- if should_include_field:
371
- responseArgStr += "\n"
372
- return responseArgStr
373
-
374
- def createRawBinaryRequest(args, configuration):
375
- """Handle multipart/form-data requests for file uploads and binary content"""
376
- params = vars(args)
377
-
378
-
379
- # Parse the JSON body
380
- try:
381
- body = json.loads(params["json"])
382
- except ValueError as e:
383
- print("ERROR: JSON argument must be valid json. ", e)
384
- return
385
- except Exception as e:
386
- print("ERROR: ", e)
387
- return
388
-
389
- # Build form data
390
- form_fields = {}
391
- files = []
392
-
393
- # Add the operations field containing the GraphQL payload
394
- form_fields['operations'] = json.dumps(body)
395
-
396
- # Handle file mappings if files are specified
397
- if hasattr(args, 'files') and args.files:
398
- # Build the map object for file uploads
399
- file_map = {}
400
- for i, (field_name, file_path) in enumerate(args.files):
401
- file_index = str(i + 1)
402
- file_map[file_index] = [field_name]
403
-
404
- # Read file content
405
- try:
406
- with open(file_path, 'rb') as f:
407
- file_content = f.read()
408
- files.append((file_index, (os.path.basename(file_path), file_content, 'application/octet-stream')))
409
- except IOError as e:
410
- print(f"ERROR: Could not read file {file_path}: {e}")
411
- return
412
-
413
- # Add the map field
414
- form_fields['map'] = json.dumps(file_map)
415
-
416
- # Test mode - just print the request structure
417
- if params.get("t") == True:
418
- print("Multipart form data request:")
419
- if params.get("p") == True:
420
- print(f"Operations: {json.dumps(json.loads(form_fields.get('operations')), indent=2)}")
421
- else:
422
- print(f"Operations: {form_fields.get('operations')}")
423
- if 'map' in form_fields:
424
- print(f"Map: {form_fields.get('map')}")
425
- if files:
426
- print(f"Files: {[f[0] + ': ' + f[1][0] for f in files]}")
427
- return None
428
-
429
- # Perform the multipart request
430
- try:
431
- return sendMultipartRequest(configuration, form_fields, files, params)
432
- except Exception as e:
433
- # Safely handle exception string conversion
434
- try:
435
- error_str = str(e)
436
- except Exception:
437
- error_str = f"Exception of type {type(e).__name__}"
438
-
439
- if params.get("v") == True:
440
- import traceback
441
- print(f"ERROR: Failed to send multipart request: {error_str}")
442
- traceback.print_exc()
443
- else:
444
- print(f"ERROR: Failed to send multipart request: {error_str}")
445
- return None
446
-
447
- def get_private_help(command_name, command_config):
448
- """Generate comprehensive help text for a private command"""
449
- usage = f"catocli private {command_name}"
450
-
451
- # Create comprehensive JSON example with all arguments (excluding accountId)
452
- if 'arguments' in command_config:
453
- json_example = {}
454
- for arg in command_config['arguments']:
455
- arg_name = arg.get('name')
456
- # Skip accountId since it's handled by standard -accountID CLI argument
457
- if arg_name and arg_name.lower() != 'accountid':
458
- if 'example' in arg:
459
- # Use explicit example if provided
460
- json_example[arg_name] = arg['example']
461
- elif 'default' in arg:
462
- # Use default value if available
463
- json_example[arg_name] = arg['default']
464
- else:
465
- # Generate placeholder based on type
466
- arg_type = arg.get('type', 'string')
467
- if arg_type == 'string':
468
- json_example[arg_name] = f"<{arg_name}>"
469
- elif arg_type == 'object':
470
- if 'struct' in arg:
471
- # Use struct definition
472
- json_example[arg_name] = arg['struct']
473
- else:
474
- json_example[arg_name] = {}
475
- else:
476
- json_example[arg_name] = f"<{arg_name}>"
477
-
478
- if json_example:
479
- # Format JSON nicely for readability in help
480
- json_str = json.dumps(json_example, indent=2)
481
- usage += f" '{json_str}'"
482
-
483
- # Add common options
484
- usage += " [-t] [-v] [-p]"
485
-
486
- # Add command-specific arguments with descriptions (excluding accountId)
487
- if 'arguments' in command_config:
488
- filtered_args = [arg for arg in command_config['arguments'] if arg.get('name', '').lower() != 'accountid']
489
- if filtered_args:
490
- usage += "\n\nArguments:"
491
- for arg in filtered_args:
492
- arg_name = arg.get('name')
493
- arg_type = arg.get('type', 'string')
494
- arg_default = arg.get('default')
495
- arg_example = arg.get('example')
496
-
497
- if arg_name:
498
- usage += f"\n --{arg_name}: {arg_type}"
499
- if arg_default is not None:
500
- usage += f" (default: {arg_default})"
501
- if arg_example is not None and arg_example != arg_default:
502
- usage += f" (example: {json.dumps(arg_example) if isinstance(arg_example, (dict, list)) else arg_example})"
503
-
504
- # Add standard accountID information
505
- usage += "\n\nStandard Arguments:"
506
- usage += "\n -accountID: Account ID (taken from profile, can be overridden)"
507
-
508
- # Add payload file info if available
509
- if 'payloadFilePath' in command_config:
510
- usage += f"\n\nPayload template: {command_config['payloadFilePath']}"
511
-
512
- # Add batch processing info if configured
513
- if 'batchSize' in command_config:
514
- usage += f"\nBatch size: {command_config['batchSize']}"
515
- if 'paginationParam' in command_config:
516
- usage += f" (pagination: {command_config['paginationParam']})"
517
-
518
- return usage
519
-
520
-
521
- def load_payload_template(command_config):
522
- """Load and return the GraphQL payload template for a private command"""
523
- try:
524
- payload_path = command_config.get('payloadFilePath')
525
- if not payload_path:
526
- raise ValueError(f"Missing payloadFilePath in command configuration")
527
-
528
- # Construct the full path relative to the settings directory
529
- settings_dir = os.path.expanduser("~/.cato")
530
- full_payload_path = os.path.join(settings_dir, payload_path)
531
-
532
- # Load the payload file using the standard JSON loading mechanism
533
- try:
534
- with open(full_payload_path, 'r') as f:
535
- return json.load(f)
536
- except FileNotFoundError:
537
- raise ValueError(f"Payload file not found: {full_payload_path}")
538
- except json.JSONDecodeError as e:
539
- raise ValueError(f"Invalid JSON in payload file {full_payload_path}: {e}")
540
- except Exception as e:
541
- raise ValueError(f"Failed to load payload template: {e}")
542
-
543
-
544
- def set_nested_value(obj, path, value):
545
- """Set a value at a nested path in an object using jQuery-style JSON path syntax
546
-
547
- Supports:
548
- - Simple dot notation: 'a.b.c'
549
- - Array access: 'a.b[0].c' or 'a.b[0]'
550
- - Mixed paths: 'variables.filters[0].search'
551
- - Deep nesting: 'data.results[0].items[1].properties.name'
552
- """
553
- import re
554
-
555
- # Parse the path into components handling both dot notation and array indices
556
- # Split by dots first, then handle array indices
557
- path_parts = []
558
- for part in path.split('.'):
559
- # Check if this part contains array notation like 'items[0]'
560
- array_matches = re.findall(r'([^\[]+)(?:\[(\d+)\])?', part)
561
- for match in array_matches:
562
- key, index = match
563
- if key: # Add the key part
564
- path_parts.append(key)
565
- if index: # Add the array index part
566
- path_parts.append(int(index))
567
-
568
- current = obj
569
-
570
- # Navigate to the parent of the target location
571
- for i, part in enumerate(path_parts[:-1]):
572
- next_part = path_parts[i + 1]
573
-
574
- if isinstance(part, int):
575
- # Current part is an array index
576
- if not isinstance(current, list):
577
- raise ValueError(f"Expected array at path component {i}, got {type(current).__name__}")
578
-
579
- # Extend array if necessary
580
- while len(current) <= part:
581
- current.append(None)
582
-
583
- # Initialize the array element if it doesn't exist
584
- if current[part] is None:
585
- if isinstance(next_part, int):
586
- current[part] = [] # Next part is array index, so create array
587
- else:
588
- current[part] = {} # Next part is object key, so create object
589
-
590
- current = current[part]
591
-
592
- else:
593
- # Current part is an object key
594
- if not isinstance(current, dict):
595
- raise ValueError(f"Expected object at path component {i}, got {type(current).__name__}")
596
-
597
- # Create the key if it doesn't exist
598
- if part not in current:
599
- if isinstance(next_part, int):
600
- current[part] = [] # Next part is array index, so create array
601
- else:
602
- current[part] = {} # Next part is object key, so create object
603
-
604
- current = current[part]
605
-
606
- # Set the final value
607
- final_part = path_parts[-1]
608
- if isinstance(final_part, int):
609
- # Final part is an array index
610
- if not isinstance(current, list):
611
- raise ValueError(f"Expected array at final path component, got {type(current).__name__}")
612
-
613
- # Extend array if necessary
614
- while len(current) <= final_part:
615
- current.append(None)
616
-
617
- current[final_part] = value
618
- else:
619
- # Final part is an object key
620
- if not isinstance(current, dict):
621
- raise ValueError(f"Expected object at final path component, got {type(current).__name__}")
622
-
623
- current[final_part] = value
624
-
625
-
626
- def apply_template_variables(template, variables, private_config):
627
- """Apply variables to the template using path-based insertion and template replacement"""
628
- if not template or not isinstance(template, dict):
629
- return template
630
-
631
- # Make a deep copy to avoid modifying the original
632
- import copy
633
- result = copy.deepcopy(template)
634
-
635
- # First, handle path-based variable insertion from private_config
636
- if private_config and 'arguments' in private_config:
637
- for arg in private_config['arguments']:
638
- arg_name = arg.get('name')
639
- arg_paths = arg.get('path', [])
640
-
641
- if arg_name and arg_name in variables and arg_paths:
642
- # Insert the variable value at each specified path
643
- for path in arg_paths:
644
- try:
645
- set_nested_value(result, path, variables[arg_name])
646
- except Exception as e:
647
- # If path insertion fails, continue to template replacement
648
- pass
649
-
650
- # Second, handle traditional template variable replacement as fallback
651
- def traverse_and_replace(obj, path=""):
652
- if isinstance(obj, dict):
653
- for key, value in list(obj.items()):
654
- new_path = f"{path}.{key}" if path else key
655
-
656
- # Check if this is a template variable (string that starts with '{{')
657
- if isinstance(value, str) and value.startswith('{{') and value.endswith('}}'):
658
- # Extract variable name
659
- var_name = value[2:-2].strip()
660
-
661
- # Replace with actual value if available
662
- if var_name in variables:
663
- obj[key] = variables[var_name]
664
-
665
- # Recursively process nested objects
666
- else:
667
- traverse_and_replace(value, new_path)
668
-
669
- elif isinstance(obj, list):
670
- for i, item in enumerate(obj):
671
- traverse_and_replace(item, f"{path}[{i}]")
672
-
673
- traverse_and_replace(result)
674
- return result
675
-
676
-
677
- def createPrivateRequest(args, configuration):
678
- """Handle private command execution using GraphQL payload templates"""
679
- params = vars(args)
680
-
681
- # Get the private command configuration
682
- private_command = params.get('private_command')
683
- private_config = params.get('private_config')
684
-
685
- if not private_command or not private_config:
686
- print("ERROR: Missing private command configuration")
687
- return None
688
-
689
- # Load private settings and apply ONLY for private commands
690
- try:
691
- settings_file = os.path.expanduser("~/.cato/settings.json")
692
- with open(settings_file, 'r') as f:
693
- private_settings = json.load(f)
694
- except (FileNotFoundError, json.JSONDecodeError):
695
- private_settings = {}
696
-
697
- # Override endpoint if specified in private settings
698
- if 'baseUrl' in private_settings:
699
- configuration.host = private_settings['baseUrl']
700
-
701
- # Add custom headers from private settings
702
- if 'headers' in private_settings and isinstance(private_settings['headers'], dict):
703
- if not hasattr(configuration, 'custom_headers'):
704
- configuration.custom_headers = {}
705
- for key, value in private_settings['headers'].items():
706
- configuration.custom_headers[key] = value
707
-
708
- # Parse input JSON variables
709
- try:
710
- variables = json.loads(params.get('json', '{}'))
711
- except ValueError as e:
712
- print(f"ERROR: Invalid JSON input: {e}")
713
- return None
714
-
715
- # Apply default values from settings configuration first
716
- for arg in private_config.get('arguments', []):
717
- arg_name = arg.get('name')
718
- if arg_name and 'default' in arg:
719
- variables[arg_name] = arg['default']
720
-
721
- # Apply profile account ID as fallback (lower priority than settings defaults)
722
- # Only apply if accountId is not already set by settings defaults
723
- if configuration and hasattr(configuration, 'accountID'):
724
- if 'accountID' not in variables and 'accountId' not in variables:
725
- # Use both naming conventions to support different payload templates
726
- variables['accountID'] = configuration.accountID
727
- variables['accountId'] = configuration.accountID
728
- # If accountId/accountID exists but not the other variation, add both
729
- elif 'accountID' in variables and 'accountId' not in variables:
730
- variables['accountId'] = variables['accountID']
731
- elif 'accountId' in variables and 'accountID' not in variables:
732
- variables['accountID'] = variables['accountId']
733
-
734
- # Apply CLI argument values (highest priority - overrides everything)
735
- for arg in private_config.get('arguments', []):
736
- arg_name = arg.get('name')
737
- if arg_name:
738
- # Handle special case for accountId - CLI uses -accountID but config uses accountId
739
- if arg_name.lower() == 'accountid':
740
- if hasattr(args, 'accountID') and getattr(args, 'accountID') is not None:
741
- arg_value = getattr(args, 'accountID')
742
- variables['accountID'] = arg_value
743
- variables['accountId'] = arg_value
744
- elif hasattr(args, 'accountId') and getattr(args, 'accountId') is not None:
745
- arg_value = getattr(args, 'accountId')
746
- variables['accountID'] = arg_value
747
- variables['accountId'] = arg_value
748
- # Handle other arguments normally
749
- else:
750
- if hasattr(args, arg_name):
751
- arg_value = getattr(args, arg_name)
752
- if arg_value is not None:
753
- variables[arg_name] = arg_value
754
-
755
- # Load the payload template
756
- try:
757
- payload_template = load_payload_template(private_config)
758
- except ValueError as e:
759
- print(f"ERROR: {e}")
760
- return None
761
-
762
- # Apply variables to the template using path-based insertion
763
- body = apply_template_variables(payload_template, variables, private_config)
764
-
765
- # Test mode - just print the request
766
- if params.get('t'):
767
- if params.get('p'):
768
- print(json.dumps(body, indent=2, sort_keys=True))
769
- else:
770
- print(json.dumps(body))
771
- return None
772
-
773
- # Execute the GraphQL request using custom method (no User-Agent header)
774
- try:
775
- return sendPrivateGraphQLRequest(configuration, body, params)
776
- except Exception as e:
777
- return e
778
-
779
-
780
- def sendMultipartRequest(configuration, form_fields, files, params):
781
- """Send a multipart/form-data request directly using urllib3"""
782
- import urllib3
783
-
784
- # Create pool manager
785
- pool_manager = urllib3.PoolManager(
786
- cert_reqs='CERT_NONE' if not getattr(configuration, 'verify_ssl', False) else 'CERT_REQUIRED'
787
- )
788
-
789
- # Prepare form data
790
- fields = []
791
- for key, value in form_fields.items():
792
- fields.append((key, value))
793
-
794
- for file_key, (filename, content, content_type) in files:
795
- fields.append((file_key, (filename, content, content_type)))
796
-
797
- # Encode multipart data
798
- body_data, content_type = encode_multipart_formdata(fields)
799
-
800
- # Prepare headers
801
- headers = {
802
- 'Content-Type': content_type,
803
- 'User-Agent': f"Cato-CLI-v{getattr(configuration, 'version', 'unknown')}"
804
- }
805
-
806
- # Add API key if not using headers file or custom headers
807
- using_custom_headers = hasattr(configuration, 'custom_headers') and configuration.custom_headers
808
- if not using_custom_headers and hasattr(configuration, 'api_key') and hasattr(configuration, 'api_key') and configuration.api_key and 'x-api-key' in configuration.api_key:
809
- headers['x-api-key'] = configuration.api_key['x-api-key']
810
-
811
- # Add custom headers
812
- if using_custom_headers:
813
- headers.update(configuration.custom_headers)
814
-
815
- # Verbose output
816
- if params.get("v") == True:
817
- print(f"Host: {getattr(configuration, 'host', 'unknown')}")
818
- masked_headers = headers.copy()
819
- if 'x-api-key' in masked_headers:
820
- masked_headers['x-api-key'] = '***MASKED***'
821
- print(f"Request Headers: {json.dumps(masked_headers, indent=4, sort_keys=True)}")
822
- print(f"Content-Type: {content_type}")
823
- print(f"Form fields: {list(form_fields.keys())}")
824
- print(f"Files: {[f[0] for f in files]}\n")
825
-
826
- try:
827
- # Make the request
828
- resp = pool_manager.request(
829
- 'POST',
830
- getattr(configuration, 'host', 'https://api.catonetworks.com/api/v1/graphql'),
831
- body=body_data,
832
- headers=headers
833
- )
834
-
835
- # Parse response
836
- if resp.status < 200 or resp.status >= 300:
837
- reason = resp.reason if resp.reason is not None else "Unknown Error"
838
- error_msg = f"HTTP {resp.status}: {reason}"
839
- if resp.data:
840
- try:
841
- error_msg += f"\n{resp.data.decode('utf-8')}"
842
- except Exception:
843
- error_msg += f"\n{resp.data}"
844
- print(f"ERROR: {error_msg}")
845
- return None
846
-
847
- try:
848
- response_data = json.loads(resp.data.decode('utf-8'))
849
- except json.JSONDecodeError:
850
- response_data = resp.data.decode('utf-8')
851
-
852
- return [response_data]
853
-
854
- except Exception as e:
855
- # Safely handle exception string conversion
856
- try:
857
- error_str = str(e)
858
- except Exception:
859
- error_str = f"Exception of type {type(e).__name__}"
860
- print(f"ERROR: Network/request error: {error_str}")
861
- return None
862
-
863
-
864
- def sendPrivateGraphQLRequest(configuration, body, params):
865
- """Send a GraphQL request for private commands without User-Agent header"""
866
- import urllib3
867
-
868
- # Create pool manager
869
- pool_manager = urllib3.PoolManager(
870
- cert_reqs='CERT_NONE' if not getattr(configuration, 'verify_ssl', False) else 'CERT_REQUIRED'
871
- )
872
-
873
- # Prepare headers WITHOUT User-Agent
874
- headers = {
875
- 'Content-Type': 'application/json'
876
- }
877
-
878
- # Add API key if not using headers file or custom headers
879
- using_custom_headers = hasattr(configuration, 'custom_headers') and configuration.custom_headers
880
- if not using_custom_headers and hasattr(configuration, 'api_key') and configuration.api_key and 'x-api-key' in configuration.api_key:
881
- headers['x-api-key'] = configuration.api_key['x-api-key']
882
-
883
- # Add custom headers
884
- if using_custom_headers:
885
- headers.update(configuration.custom_headers)
886
-
887
- # Encode headers to handle Unicode characters properly
888
- encoded_headers = {}
889
- for key, value in headers.items():
890
- # Ensure header values are properly encoded as strings
891
- if isinstance(value, str):
892
- # Replace problematic Unicode characters that can't be encoded in latin-1
893
- value = value.encode('utf-8', errors='replace').decode('latin-1', errors='replace')
894
- encoded_headers[key] = value
895
- headers = encoded_headers
896
-
897
- # Verbose output
898
- if params.get("v") == True:
899
- print(f"Host: {getattr(configuration, 'host', 'unknown')}")
900
- masked_headers = headers.copy()
901
- if 'x-api-key' in masked_headers:
902
- masked_headers['x-api-key'] = '***MASKED***'
903
- # Also mask Cookie for privacy
904
- if 'Cookie' in masked_headers:
905
- masked_headers['Cookie'] = '***MASKED***'
906
- print(f"Request Headers: {json.dumps(masked_headers, indent=4, sort_keys=True)}")
907
- print(f"Request Data: {json.dumps(body, indent=4, sort_keys=True)}\n")
908
-
909
- # Prepare request body
910
- body_data = json.dumps(body).encode('utf-8')
911
-
912
- try:
913
- # Make the request
914
- resp = pool_manager.request(
915
- 'POST',
916
- getattr(configuration, 'host', 'https://api.catonetworks.com/api/v1/graphql'),
917
- body=body_data,
918
- headers=headers
919
- )
920
-
921
- # Parse response
922
- if resp.status < 200 or resp.status >= 300:
923
- reason = resp.reason if resp.reason is not None else "Unknown Error"
924
- error_msg = f"HTTP {resp.status}: {reason}"
925
- if resp.data:
926
- try:
927
- error_msg += f"\n{resp.data.decode('utf-8')}"
928
- except Exception:
929
- error_msg += f"\n{resp.data}"
930
- print(f"ERROR: {error_msg}")
931
- return None
932
-
933
- try:
934
- response_data = json.loads(resp.data.decode('utf-8'))
935
- except json.JSONDecodeError:
936
- response_data = resp.data.decode('utf-8')
937
-
938
- # Return in the same format as the regular API client
939
- return [response_data]
940
-
941
- except Exception as e:
942
- # Safely handle exception string conversion
943
- try:
944
- error_str = str(e)
945
- except Exception:
946
- error_str = f"Exception of type {type(e).__name__}"
947
- print(f"ERROR: Network/request error: {error_str}")
948
- return None