cloud-governance 1.1.402__tar.gz → 1.1.404__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. {cloud_governance-1.1.402/cloud_governance.egg-info → cloud_governance-1.1.404}/PKG-INFO +2 -2
  2. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/main/environment_variables.py +6 -2
  3. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/main/main.py +1 -1
  4. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/monthly_report.py +11 -2
  5. cloud_governance-1.1.404/cloud_governance/policy/aws/yearly_savings_report.py +490 -0
  6. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/zombie_non_cluster/run_zombie_non_cluster_policies.py +1 -1
  7. {cloud_governance-1.1.402 → cloud_governance-1.1.404/cloud_governance.egg-info}/PKG-INFO +2 -2
  8. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance.egg-info/SOURCES.txt +1 -0
  9. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/setup.py +2 -2
  10. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/LICENSE +0 -0
  11. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/MANIFEST.in +0 -0
  12. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/README.md +0 -0
  13. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/__init__.py +0 -0
  14. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/__init__.py +0 -0
  15. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/__init__.py +0 -0
  16. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/aws/__init__.py +0 -0
  17. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/aws/ec2/__init__.py +0 -0
  18. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/aws/ec2/aws_monitor_tickets.py +0 -0
  19. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/aws/ec2/aws_tagging_operations.py +0 -0
  20. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/aws/ec2/collect_cro_reports.py +0 -0
  21. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/aws/ec2/cost_over_usage.py +0 -0
  22. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/aws/ec2/monitor_cro_instances.py +0 -0
  23. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/aws/ec2/run_cro.py +0 -0
  24. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/aws/ec2/tag_cro_instances.py +0 -0
  25. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/azure/__init__.py +0 -0
  26. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/azure/resource_groups/__init__.py +0 -0
  27. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/azure/resource_groups/abstract_resource.py +0 -0
  28. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/azure/resource_groups/azure_monitor_tickets.py +0 -0
  29. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/azure/resource_groups/azure_tagging_operations.py +0 -0
  30. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/azure/resource_groups/collect_cro_reports.py +0 -0
  31. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/azure/resource_groups/cost_over_usage.py +0 -0
  32. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/azure/resource_groups/monitor_cro_resources.py +0 -0
  33. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/azure/resource_groups/tag_cro_resources.py +0 -0
  34. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/common/__init__.py +0 -0
  35. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/common/abstract_collect_cro_reports.py +0 -0
  36. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/common/abstract_cost_over_usage.py +0 -0
  37. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/clouds/common/abstract_tagging_operations.py +0 -0
  38. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/common/__init__.py +0 -0
  39. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/common/abstract_monitor_tickets.py +0 -0
  40. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/common/cro_object.py +0 -0
  41. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/common/run_cro.py +0 -0
  42. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/monitor/__init__.py +0 -0
  43. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/monitor/cloud_monitor.py +0 -0
  44. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/utils/__init__.py +0 -0
  45. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/utils/common_operations.py +0 -0
  46. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/utils/constant_variables.py +0 -0
  47. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/cloud_resource_orchestration/utils/elastic_search_queries.py +0 -0
  48. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/__init__.py +0 -0
  49. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/__init__.py +0 -0
  50. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/__init__.py +0 -0
  51. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/athena/__init__.py +0 -0
  52. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/athena/abstract_athena_operations.py +0 -0
  53. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/athena/boto3_client_athena_operations.py +0 -0
  54. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/athena/pyathena_operations.py +0 -0
  55. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/cloudtrail/__init__.py +0 -0
  56. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/cloudtrail/cloudtrail_operations.py +0 -0
  57. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/cloudwatch/__init__.py +0 -0
  58. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/cloudwatch/cloudwatch_operations.py +0 -0
  59. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/cost_explorer/__init__.py +0 -0
  60. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/cost_explorer/cost_explorer_operations.py +0 -0
  61. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/dynamodb/__init__.py +0 -0
  62. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/dynamodb/dynamodb_operations.py +0 -0
  63. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/ec2/__init__.py +0 -0
  64. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/ec2/ec2_operations.py +0 -0
  65. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/iam/__init__.py +0 -0
  66. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/iam/iam_operations.py +0 -0
  67. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/price/__init__.py +0 -0
  68. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/price/price.py +0 -0
  69. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/price/resources_pricing.py +0 -0
  70. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/rds/__init__.py +0 -0
  71. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/rds/rds_operations.py +0 -0
  72. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/resource_explorer/__init__.py +0 -0
  73. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/resource_explorer/resource_explorer_operations.py +0 -0
  74. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/resource_tagging_api/__init__.py +0 -0
  75. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/resource_tagging_api/resource_tag_api_operations.py +0 -0
  76. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/s3/__init__.py +0 -0
  77. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/s3/s3_operations.py +0 -0
  78. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/savingsplan/__init__.py +0 -0
  79. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/savingsplan/savings_plans_operations.py +0 -0
  80. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/sts/__init__.py +0 -0
  81. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/sts/sts_oprations.py +0 -0
  82. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/support/__init__.py +0 -0
  83. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/support/support_operations.py +0 -0
  84. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/utils/__init__.py +0 -0
  85. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/utils/common_methods.py +0 -0
  86. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/aws/utils/utils.py +0 -0
  87. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/azure/__init__.py +0 -0
  88. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/azure/common/__init__.py +0 -0
  89. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/azure/common/common_operations.py +0 -0
  90. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/azure/compute/__init__.py +0 -0
  91. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/azure/compute/compute_operations.py +0 -0
  92. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/azure/compute/network_operations.py +0 -0
  93. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/azure/compute/resource_group_operations.py +0 -0
  94. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/azure/cost_management/__init__.py +0 -0
  95. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/azure/cost_management/cost_management_operations.py +0 -0
  96. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/azure/monitor/__init__.py +0 -0
  97. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/azure/monitor/monitor_management_operations.py +0 -0
  98. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/azure/subscriptions/__init__.py +0 -0
  99. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/azure/subscriptions/azure_operations.py +0 -0
  100. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/cloudability/__init__.py +0 -0
  101. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/cloudability/cloudability_operations.py +0 -0
  102. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/cloudability/templates/__init__.py +0 -0
  103. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/cloudability/templates/cloudability_dimensions.py +0 -0
  104. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/gcp/__init__.py +0 -0
  105. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/gcp/google_account.py +0 -0
  106. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/ibm/__init__.py +0 -0
  107. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/ibm/account/__init__.py +0 -0
  108. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/ibm/account/ibm_account.py +0 -0
  109. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/ibm/account/ibm_authenticator.py +0 -0
  110. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/ibm/classic/__init__.py +0 -0
  111. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/ibm/classic/classic_operations.py +0 -0
  112. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/ibm/developer_tools/__init__.py +0 -0
  113. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/ibm/developer_tools/schematic_operations.py +0 -0
  114. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/ibm/platform_services/__init__.py +0 -0
  115. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/ibm/platform_services/platform_service_operations.py +0 -0
  116. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/ibm/tagging/__init__.py +0 -0
  117. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/ibm/tagging/global_tagging_operations.py +0 -0
  118. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/ibm/vpc/__init__.py +0 -0
  119. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/clouds/ibm/vpc/vpc_infra_operations.py +0 -0
  120. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/elasticsearch/__init__.py +0 -0
  121. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/elasticsearch/elastic_upload.py +0 -0
  122. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/elasticsearch/elasticsearch_exceptions.py +0 -0
  123. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/elasticsearch/elasticsearch_operations.py +0 -0
  124. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/elasticsearch/modals/__init__.py +0 -0
  125. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/elasticsearch/modals/cost_usage_reports_data.py +0 -0
  126. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/elasticsearch/modals/policy_es_data.py +0 -0
  127. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/google_drive/__init__.py +0 -0
  128. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/google_drive/gcp_operations.py +0 -0
  129. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/google_drive/google_drive_operations.py +0 -0
  130. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/google_drive/upload_to_gsheet.py +0 -0
  131. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/jira/__init__.py +0 -0
  132. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/jira/jira.py +0 -0
  133. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/jira/jira_exceptions.py +0 -0
  134. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/jira/jira_operations.py +0 -0
  135. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/ldap/__init__.py +0 -0
  136. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/ldap/ldap_search.py +0 -0
  137. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/logger/__init__.py +0 -0
  138. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/logger/init_logger.py +0 -0
  139. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/logger/logger_time_stamp.py +0 -0
  140. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/mails/__init__.py +0 -0
  141. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/mails/gmail.py +0 -0
  142. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/mails/mail_message.py +0 -0
  143. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/mails/postfix.py +0 -0
  144. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/mails/templates/cro_monitor_budget_remain_alert.j2 +0 -0
  145. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/mails/templates/cro_monitor_budget_remain_high_alert.j2 +0 -0
  146. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/mails/templates/cro_request_for_manager_approval.j2 +0 -0
  147. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/mails/templates/policy_alert_agg_message.j2 +0 -0
  148. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/pandas/__init__.py +0 -0
  149. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/pandas/pandas_operations.py +0 -0
  150. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/tool/__init__.py +0 -0
  151. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/tool/tool.py +0 -0
  152. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/utils/__init__.py +0 -0
  153. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/utils/api_requests.py +0 -0
  154. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/utils/configs.py +0 -0
  155. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/utils/json_datetime_encoder.py +0 -0
  156. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/common/utils/utils.py +0 -0
  157. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/main/__init__.py +0 -0
  158. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/main/environment_variables_exceptions.py +0 -0
  159. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/main/es_uploader.py +0 -0
  160. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/main/main_common_operations.py +0 -0
  161. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/main/main_oerations/__init__.py +0 -0
  162. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/main/main_oerations/main_operations.py +0 -0
  163. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/main/run_cloud_resource_orchestration.py +0 -0
  164. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/__init__.py +0 -0
  165. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/__init__.py +0 -0
  166. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/cleanup/__init__.py +0 -0
  167. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/cleanup/database_idle.py +0 -0
  168. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/cleanup/instance_idle.py +0 -0
  169. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/cleanup/instance_run.py +0 -0
  170. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/cleanup/unattached_volume.py +0 -0
  171. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/cleanup/unused_nat_gateway.py +0 -0
  172. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/cost_billing_reports.py +0 -0
  173. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/cost_explorer.py +0 -0
  174. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/cost_explorer_payer_billings.py +0 -0
  175. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/cost_over_usage.py +0 -0
  176. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/ebs_in_use.py +0 -0
  177. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/ec2_stop.py +0 -0
  178. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/empty_roles.py +0 -0
  179. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/ip_unattached.py +0 -0
  180. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/monitor/__init__.py +0 -0
  181. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/monitor/cluster_run.py +0 -0
  182. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/optimize_resources_report.py +0 -0
  183. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/s3_inactive.py +0 -0
  184. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/skipped_resources.py +0 -0
  185. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/spot_savings_analysis.py +0 -0
  186. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/unused_access_key.py +0 -0
  187. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/zombie_cluster_resource.py +0 -0
  188. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/aws/zombie_snapshots.py +0 -0
  189. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/azure/__init__.py +0 -0
  190. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/azure/cleanup/__init__.py +0 -0
  191. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/azure/cleanup/instance_idle.py +0 -0
  192. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/azure/cleanup/instance_run.py +0 -0
  193. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/azure/cleanup/ip_unattached.py +0 -0
  194. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/azure/cleanup/unattached_volume.py +0 -0
  195. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/azure/cleanup/unused_nat_gateway.py +0 -0
  196. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/azure/cost_billing_reports.py +0 -0
  197. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/azure/tag_azure_resource_group.py +0 -0
  198. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/common_policies/__init__.py +0 -0
  199. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/common_policies/cloudability_cost_reports.py +0 -0
  200. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/common_policies/send_aggregated_alerts.py +0 -0
  201. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/gcp/__init__.py +0 -0
  202. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/gcp/cost_billing_reports.py +0 -0
  203. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/helpers/__init__.py +0 -0
  204. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/helpers/abstract_policy_operations.py +0 -0
  205. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/helpers/aws/__init__.py +0 -0
  206. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/helpers/aws/aws_policy_operations.py +0 -0
  207. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/helpers/azure/__init__.py +0 -0
  208. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/helpers/azure/azure_policy_operations.py +0 -0
  209. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/helpers/cloudability_operations.py +0 -0
  210. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/ibm/__init__.py +0 -0
  211. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/ibm/cost_billing_reports.py +0 -0
  212. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/ibm/cost_usage_reports.py +0 -0
  213. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/ibm/ibm_cost_over_usage.py +0 -0
  214. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/ibm/ibm_cost_report.py +0 -0
  215. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/ibm/tag_baremetal.py +0 -0
  216. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/ibm/tag_resources.py +0 -0
  217. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/ibm/tag_vm.py +0 -0
  218. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/__init__.py +0 -0
  219. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/__init__.py +0 -0
  220. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/cost_expenditure/__init__.py +0 -0
  221. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/cost_expenditure/cost_report_policies.py +0 -0
  222. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/dynamodb_upload_data/__init__.py +0 -0
  223. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/dynamodb_upload_data/cloudtrail_to_dynamodb.py +0 -0
  224. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/dynamodb_upload_data/upload_data_to_dynamodb.py +0 -0
  225. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_cluster/__init__.py +0 -0
  226. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_cluster/remove_cluster_tags.py +0 -0
  227. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_cluster/run_tag_cluster_resouces.py +0 -0
  228. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_cluster/tag_cluster_operations.py +0 -0
  229. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_cluster/tag_cluster_resouces.py +0 -0
  230. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_non_cluster/__init__.py +0 -0
  231. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_non_cluster/non_cluster_operations.py +0 -0
  232. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_non_cluster/remove_non_cluster_tags.py +0 -0
  233. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_non_cluster/run_tag_non_cluster_resources.py +0 -0
  234. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_non_cluster/tag_non_cluster_resources.py +0 -0
  235. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_non_cluster/update_na_tag_resources.py +0 -0
  236. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_user/__init__.py +0 -0
  237. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_user/iam_user_tags.py +0 -0
  238. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_user/remove_user_tags.py +0 -0
  239. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_user/run_tag_iam_user.py +0 -0
  240. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/tag_user/tag_iam_user.py +0 -0
  241. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/zombie_cluster/__init__.py +0 -0
  242. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/zombie_cluster/delete_ec2_resources.py +0 -0
  243. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/zombie_cluster/delete_iam_resources.py +0 -0
  244. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/zombie_cluster/delete_s3_resources.py +0 -0
  245. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/zombie_cluster/run_zombie_cluster_resources.py +0 -0
  246. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/zombie_cluster/validate_zombies.py +0 -0
  247. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/zombie_cluster/zombie_cluster_common_methods.py +0 -0
  248. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/zombie_non_cluster/__init__.py +0 -0
  249. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/aws/zombie_non_cluster/zombie_non_cluster_polices.py +0 -0
  250. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/azure/__init__.py +0 -0
  251. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/azure/azure_policy_runner.py +0 -0
  252. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/gcp/__init__.py +0 -0
  253. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/gcp/gcp_policy_runner.py +0 -0
  254. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/gitleaks/__init__.py +0 -0
  255. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/gitleaks/gitleaks.py +0 -0
  256. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/ibm/__init__.py +0 -0
  257. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/ibm/ibm_operations/__init__.py +0 -0
  258. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/ibm/ibm_operations/ibm_operations.py +0 -0
  259. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/ibm/ibm_operations/ibm_policy_runner.py +0 -0
  260. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/ibm/tagging/__init__.py +0 -0
  261. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_operations/ibm/tagging/tagging_operations.py +0 -0
  262. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_runners/__init__.py +0 -0
  263. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_runners/aws/__init__.py +0 -0
  264. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_runners/aws/policy_runner.py +0 -0
  265. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_runners/aws/upload_s3.py +0 -0
  266. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_runners/azure/__init__.py +0 -0
  267. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_runners/azure/policy_runner.py +0 -0
  268. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_runners/common/__init__.py +0 -0
  269. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_runners/common/abstract_policy_runner.py +0 -0
  270. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_runners/common/abstract_upload.py +0 -0
  271. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_runners/common_policy_runner.py +0 -0
  272. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_runners/elasticsearch/__init__.py +0 -0
  273. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_runners/elasticsearch/upload_elastic_search.py +0 -0
  274. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_runners/ibm/__init__.py +0 -0
  275. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance/policy/policy_runners/ibm/policy_runner.py +0 -0
  276. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance.egg-info/dependency_links.txt +0 -0
  277. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance.egg-info/not-zip-safe +0 -0
  278. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance.egg-info/requires.txt +0 -0
  279. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/cloud_governance.egg-info/top_level.txt +0 -0
  280. {cloud_governance-1.1.402 → cloud_governance-1.1.404}/setup.cfg +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloud-governance
3
- Version: 1.1.402
3
+ Version: 1.1.404
4
4
  Summary: Cloud Governance Tool
5
5
  Home-page: https://github.com/redhat-performance/cloud-governance
6
6
  Author: Red Hat
7
- Author-email: ebattat@redhat.com, athiruma@redhat.com
7
+ Author-email: ebattat@redhat.com, pragchau@redhat.com
8
8
  License: Apache License 2.0
9
9
  Classifier: License :: OSI Approved :: Apache Software License
10
10
  Classifier: Programming Language :: Python :: 3
@@ -105,7 +105,8 @@ class EnvironmentVariables:
105
105
  self._environment_variables_dict['cluster_policies'] = ['zombie_cluster_resource']
106
106
  es_index = 'cloud-governance-policy-es-index'
107
107
  self._environment_variables_dict['cost_policies'] = ['cost_explorer', 'cost_over_usage', 'cost_billing_reports',
108
- 'cost_explorer_payer_billings', 'spot_savings_analysis']
108
+ 'cost_explorer_payer_billings', 'spot_savings_analysis',
109
+ 'yearly_savings_report']
109
110
  self._environment_variables_dict['ibm_policies'] = ['tag_baremetal', 'tag_vm', 'ibm_cost_report',
110
111
  'ibm_cost_over_usage']
111
112
  self._environment_variables_dict['azure_policies'] = ['tag_azure_resource_group']
@@ -147,6 +148,9 @@ class EnvironmentVariables:
147
148
  # ['User', 'Budget', 'Project', 'Manager']
148
149
  self._environment_variables_dict['cost_explorer_tags'] = EnvironmentVariables.get_env('cost_explorer_tags',
149
150
  '{}')
151
+ self._environment_variables_dict['yearly_savings_start_date'] = EnvironmentVariables.get_env('yearly_savings_start_date', '')
152
+ self._environment_variables_dict['yearly_savings_end_date'] = EnvironmentVariables.get_env('yearly_savings_end_date', '')
153
+ self._environment_variables_dict['yearly_savings_es_index'] = EnvironmentVariables.get_env('yearly_savings_es_index', 'cloud-governance-yearly-saving')
150
154
  # AZURE Credentials
151
155
  self._environment_variables_dict['AZURE_ACCOUNT_ID'] = EnvironmentVariables.get_env('AZURE_ACCOUNT_ID', '')
152
156
  self._environment_variables_dict['AZURE_CLIENT_ID'] = EnvironmentVariables.get_env('AZURE_CLIENT_ID', '')
@@ -279,7 +283,7 @@ class EnvironmentVariables:
279
283
  self._environment_variables_dict['POLICY_ACTIONS_DAYS'] = literal_eval(
280
284
  EnvironmentVariables.get_env('POLICY_ACTIONS_DAYS', '[]'))
281
285
  self._environment_variables_dict['DEFAULT_ADMINS'] = literal_eval(
282
- EnvironmentVariables.get_env('DEFAULT_ADMINS', '["yinsong@redhat.com", "ebattat@redhat.com"]'))
286
+ EnvironmentVariables.get_env('DEFAULT_ADMINS', '["yinsong@redhat.com", "ebattat@redhat.com", "pragchau@redhat.com"]'))
283
287
  self._environment_variables_dict['KERBEROS_USERS'] = literal_eval(
284
288
  EnvironmentVariables.get_env('KERBEROS_USERS', '[]'))
285
289
  self._environment_variables_dict['POLICIES_TO_ALERT'] = literal_eval(
@@ -244,7 +244,7 @@ def main():
244
244
  ibm_classic_infrastructure_policy_runner = IBMPolicyRunner()
245
245
 
246
246
  is_cost_explorer_policies_runner = ''
247
- if environment_variables_dict.get('PUBLIC_CLOUD_NAME').upper() == 'AWS':
247
+ if environment_variables_dict.get('PUBLIC_CLOUD_NAME') and environment_variables_dict.get('PUBLIC_CLOUD_NAME').upper() == 'AWS':
248
248
  cost_explorer_policies_runner = None
249
249
  is_cost_explorer_policies_runner = policy in environment_variables_dict.get('cost_policies')
250
250
  if is_cost_explorer_policies_runner:
@@ -17,8 +17,17 @@ class MonthlyReport:
17
17
  self._es_index = 'cloud-governance-mail-messages'
18
18
  self._es_host = self.__environment_variables_dict.get('es_host', '')
19
19
  self._es_port = self.__environment_variables_dict.get('es_port', '')
20
- self._to_mail = literal_eval(self.__environment_variables_dict.get('to_mail', '[]'))
21
- self._to_cc = literal_eval(self.__environment_variables_dict.get('cc_mail', '[]'))
20
+ to_mail_str = self.__environment_variables_dict.get('to_mail', '').strip()
21
+ if to_mail_str in ('[]', ''):
22
+ self._to_mail = []
23
+ else:
24
+ self._to_mail = [x.strip() for x in to_mail_str.split(',') if x.strip()]
25
+
26
+ cc_mail_str = self.__environment_variables_dict.get('cc_mail', '').strip()
27
+ if cc_mail_str in ('[]', ''):
28
+ self._to_cc = []
29
+ else:
30
+ self._to_cc = [x.strip() for x in cc_mail_str.split(',') if cc_mail_str.strip()]
22
31
  if self._es_host:
23
32
  self._elastic_operations = ElasticSearchOperations(es_host=self._es_host, es_port=self._es_port)
24
33
  self._postfix_mail = Postfix()
@@ -0,0 +1,490 @@
1
+ from datetime import datetime, timezone, date, timedelta
2
+ import time
3
+
4
+ from cloud_governance.common.elasticsearch.elasticsearch_operations import ElasticSearchOperations
5
+ from cloud_governance.common.elasticsearch.elastic_upload import ElasticUpload
6
+ from cloud_governance.common.logger.init_logger import logger
7
+ from cloud_governance.common.logger.logger_time_stamp import logger_time_stamp
8
+ from cloud_governance.main.environment_variables import environment_variables
9
+
10
+
11
+ class YearlySavingsReport:
12
+ """
13
+ This class aggregates yearly savings and per-month savings for the current year
14
+ from policy execution data and uploads to a dedicated ES index
15
+ Uses month-by-month queries and deduplication to avoid counting resources multiple times
16
+ """
17
+
18
+ NAT_GATEWAY_HOURLY_COST = 0.045
19
+ ELASTIC_IP_HOURLY_COST = 0.005
20
+
21
+ def __init__(self):
22
+ self.__environment_variables_dict = environment_variables.environment_variables_dict
23
+ self.__es_host = self.__environment_variables_dict.get('es_host', '')
24
+ self.__es_port = self.__environment_variables_dict.get('es_port', '')
25
+ self.__elastic_operations = ElasticSearchOperations(es_host=self.__es_host, es_port=self.__es_port) if self.__es_host else None
26
+ self.__elastic_upload = ElasticUpload()
27
+ self.__policy_es_index = self.__environment_variables_dict.get('es_index', 'cloud-governance-policy-es-index')
28
+ self.__yearly_savings_es_index = self.__environment_variables_dict.get('yearly_savings_es_index')
29
+ account = self.__environment_variables_dict.get('account', 'PERF-DEPT')
30
+ self.__account = account.upper().replace('OPENSHIFT-', '').replace('OPENSHIFT', '').strip()
31
+ # Check for custom date range from environment variables. This won't upload to ES.
32
+ self.__custom_start_date = self.__environment_variables_dict.get('yearly_savings_start_date', '')
33
+ self.__custom_end_date = self.__environment_variables_dict.get('yearly_savings_end_date', '')
34
+
35
+ def __get_last_day_of_month(self, year: int, month: int):
36
+ """
37
+ Get the last day of a month, handling leap years
38
+ @param year: Year
39
+ @param month: Month (1-12)
40
+ @return: Last day of month
41
+ """
42
+ if month == 2:
43
+ # Handle February (leap year)
44
+ if year % 4 == 0 and (year % 100 != 0 or year % 400 == 0):
45
+ return 29
46
+ else:
47
+ return 28
48
+ elif month in [4, 6, 9, 11]:
49
+ return 30
50
+ else:
51
+ return 31
52
+
53
+ def __get_savings_value(self, captured_date: date, policy_name: str):
54
+ """
55
+ @param captured_date: date object
56
+ @param policy_name: policy name
57
+ @return: calculated savings value
58
+ """
59
+ savings = 0
60
+ end_of_year = date(captured_date.year, 12, 31)
61
+ remaining_days = (end_of_year - captured_date).days
62
+
63
+ if policy_name == 'unused_nat_gateway':
64
+ savings = remaining_days * 24 * self.NAT_GATEWAY_HOURLY_COST
65
+ elif policy_name == 'ip_unattached':
66
+ savings = remaining_days * 24 * self.ELASTIC_IP_HOURLY_COST
67
+
68
+ return savings
69
+
70
+ def __process_monthly_query(self, month_start: str, month_end: str):
71
+ """
72
+ Process a single monthly query and return resource-level results
73
+ @param month_start: Start date string (YYYY-MM-DD)
74
+ @param month_end: End date string (YYYY-MM-DD)
75
+ @return: Dictionary of {resource_id: {captured_date, policy_name, savings}}
76
+ """
77
+ if not self.__elastic_operations:
78
+ return {}
79
+
80
+ query = {
81
+ "size": 0,
82
+ "query": {
83
+ "bool": {
84
+ "must": [
85
+ {
86
+ "term": {
87
+ "PublicCloud.keyword": {
88
+ "value": "AWS"
89
+ }
90
+ }
91
+ },
92
+ {
93
+ "term": {
94
+ "account.keyword": {
95
+ "value": self.__account
96
+ }
97
+ }
98
+ }
99
+ ],
100
+ "must_not": [
101
+ {
102
+ "terms": {
103
+ "policy.keyword": [
104
+ "zombie_cluster_resource", "instance_run", "ebs_in_use",
105
+ "s3_inactive", "optimize_resources_report", "instance_idle",
106
+ "cluster_run", "skipped_resources", "ec2_idle", "empty_roles",
107
+ "unused_access_key"
108
+ ]
109
+ }
110
+ }
111
+ ],
112
+ "filter": [{
113
+ "range": {
114
+ "timestamp": {
115
+ "gte": month_start,
116
+ "lte": month_end,
117
+ "format": "yyyy-MM-dd"
118
+ }
119
+ }
120
+ }]
121
+ }
122
+ },
123
+ "aggs": {
124
+ "PolicyName": {
125
+ "terms": {
126
+ "field": "policy.keyword",
127
+ "size": 20,
128
+ "order": {"_key": "desc"}
129
+ },
130
+ "aggs": {
131
+ "CapturedDate": {
132
+ "terms": {
133
+ "field": "timestamp",
134
+ "size": 10000
135
+ },
136
+ "aggs": {
137
+ "ResourceId": {
138
+ "terms": {
139
+ "field": "ResourceId.keyword",
140
+ "size": 10000,
141
+ "order": {"_key": "desc"}
142
+ },
143
+ "aggs": {
144
+ "Savings": {
145
+ "max": {
146
+ "field": "TotalYearlySavings",
147
+ "missing": 0
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
153
+ }
154
+ }
155
+ }
156
+ }
157
+ }
158
+
159
+ try:
160
+ response = self.__elastic_operations.post_query(
161
+ query=query,
162
+ es_index=self.__policy_es_index,
163
+ result_agg=True
164
+ )
165
+
166
+ if not response or 'PolicyName' not in response:
167
+ logger.warning(f'No response or unexpected structure for {month_start} to {month_end}')
168
+ return {}
169
+
170
+ monthly_resources = {}
171
+ policy_buckets = response.get('PolicyName', {}).get('buckets', [])
172
+
173
+ logger.debug(f'DEBUG: Found {len(policy_buckets)} policies in query results')
174
+ for policy in policy_buckets:
175
+ logger.debug(f'DEBUG: Policy found: {policy.get("key")} with {len(policy.get("CapturedDate", {}).get("buckets", []))} captured dates')
176
+
177
+ for policy in policy_buckets:
178
+ policy_name = policy.get('key')
179
+
180
+ for es_capture_date_values in policy.get('CapturedDate', {}).get('buckets', []):
181
+ captured_date_str = es_capture_date_values.get('key_as_string', '')
182
+
183
+ if captured_date_str:
184
+ captured_date = datetime.strptime(captured_date_str[:10], "%Y-%m-%d").date()
185
+ else:
186
+ captured_date = datetime.now(timezone.utc).date()
187
+
188
+ for resource in es_capture_date_values.get('ResourceId', {}).get('buckets', []):
189
+ resource_id = resource.get('key')
190
+ savings = resource.get('Savings', {}).get('value', 0)
191
+
192
+ if resource_id in monthly_resources:
193
+ if monthly_resources[resource_id]['captured_date'] > captured_date:
194
+ monthly_resources[resource_id]['captured_date'] = captured_date
195
+ if savings == 0:
196
+ savings = self.__get_savings_value(captured_date, policy_name)
197
+ if monthly_resources[resource_id]['savings'] > savings:
198
+ monthly_resources[resource_id]['savings'] = savings
199
+ else:
200
+ if savings == 0:
201
+ savings = self.__get_savings_value(captured_date, policy_name)
202
+ monthly_resources[resource_id] = {
203
+ 'captured_date': captured_date,
204
+ 'policy_name': policy_name,
205
+ 'savings': savings
206
+ }
207
+
208
+ policy_summary = {}
209
+ for resource_id, resource_data in monthly_resources.items():
210
+ policy_name = resource_data.get('policy_name')
211
+ savings = resource_data.get('savings', 0)
212
+ policy_summary[policy_name] = policy_summary.get(policy_name, 0) + savings
213
+
214
+ logger.info(f'Monthly resources summary by policy: {policy_summary}')
215
+ logger.info(f"Found {len(monthly_resources)} resources for {month_start} to {month_end}")
216
+ return monthly_resources
217
+
218
+ except Exception as err:
219
+ logger.error(f'Error processing month {month_start} to {month_end}: {err}')
220
+ return {}
221
+
222
+ def __calculate_month_savings(self, year: int, month: int, start_day: int, end_day: int):
223
+ """
224
+ Calculate savings for a specific month
225
+ @param year: Year
226
+ @param month: Month (1-12)
227
+ @param start_day: Start day of month
228
+ @param end_day: End day of month
229
+ @return: Dictionary of {policy_name: savings_value}
230
+ """
231
+ month_start = date(year, month, start_day).strftime("%Y-%m-%d")
232
+ month_end = date(year, month, end_day).strftime("%Y-%m-%d")
233
+
234
+ logger.info(f'Calculating savings for {month_start} to {month_end}')
235
+
236
+ return self.__get_yearly_savings(start_date=month_start, end_date=month_end)
237
+
238
+ def __get_yearly_savings(self, start_date: str = None, end_date: str = None):
239
+ """
240
+ This method returns the yearly savings of the policies.
241
+ Queries month-by-month to avoid Elasticsearch overload.
242
+ @param start_date: Start date string (YYYY-MM-DD). If None, defaults to Jan 1 of current year.
243
+ @param end_date: End date string (YYYY-MM-DD). If None, defaults to Dec 31 of current year.
244
+ @return: Dictionary of {policy_name: total_savings}
245
+ """
246
+ if not start_date:
247
+ start_date = datetime.now(timezone.utc).date().replace(day=1, month=1).strftime("%Y-%m-%d")
248
+ if not end_date:
249
+ end_date = datetime.now(timezone.utc).date().replace(day=31, month=12).strftime("%Y-%m-%d")
250
+
251
+ logger.info(f"Getting yearly savings from {start_date} to {end_date}")
252
+
253
+ monthly_ranges = self.__split_date_range_by_month(start_date, end_date)
254
+ logger.debug(f"Split into {len(monthly_ranges)} monthly queries")
255
+
256
+ all_resources = {}
257
+
258
+ for i, (month_start, month_end) in enumerate(monthly_ranges, 1):
259
+ logger.info(f"Processing month {i}/{len(monthly_ranges)}: {month_start} to {month_end}")
260
+ monthly_resources = self.__process_monthly_query(month_start, month_end)
261
+
262
+ for resource_id, resource_data in monthly_resources.items():
263
+ if resource_id in all_resources:
264
+ if all_resources[resource_id]['captured_date'] > resource_data['captured_date']:
265
+ all_resources[resource_id]['captured_date'] = resource_data['captured_date']
266
+ if all_resources[resource_id]['savings'] > resource_data['savings']:
267
+ all_resources[resource_id]['savings'] = resource_data['savings']
268
+ else:
269
+ all_resources[resource_id] = resource_data
270
+
271
+ if i < len(monthly_ranges):
272
+ time.sleep(0.5)
273
+
274
+ result = self.__get_total_policy_sum(all_resources)
275
+ return result
276
+
277
+ def __split_date_range_by_month(self, start_date: str, end_date: str):
278
+ """
279
+ Split date range into monthly chunks
280
+ @param start_date: Start date string (YYYY-MM-DD)
281
+ @param end_date: End date string (YYYY-MM-DD)
282
+ @return: List of (month_start, month_end) tuples as strings
283
+ """
284
+ if not start_date or not end_date:
285
+ raise ValueError(f"Both start_date and end_date must be provided. Got: start_date={start_date}, end_date={end_date}")
286
+
287
+ start = datetime.strptime(start_date, "%Y-%m-%d").date()
288
+ end = datetime.strptime(end_date, "%Y-%m-%d").date()
289
+
290
+ if start > end:
291
+ raise ValueError(f"start_date ({start_date}) must be <= end_date ({end_date})")
292
+
293
+ monthly_ranges = []
294
+ current_start = start
295
+
296
+ while current_start <= end:
297
+ if current_start.month == 12:
298
+ current_end = date(current_start.year + 1, 1, 1) - timedelta(days=1)
299
+ else:
300
+ current_end = date(current_start.year, current_start.month + 1, 1) - timedelta(days=1)
301
+ if current_end > end:
302
+ current_end = end
303
+ monthly_ranges.append((
304
+ current_start.strftime("%Y-%m-%d"),
305
+ current_end.strftime("%Y-%m-%d")
306
+ ))
307
+ if current_end.month == 12:
308
+ current_start = date(current_end.year + 1, 1, 1)
309
+ else:
310
+ current_start = date(current_end.year, current_end.month + 1, 1)
311
+
312
+ return monthly_ranges
313
+
314
+ def __get_total_policy_sum(self, all_resources: dict):
315
+ """
316
+ Calculate total savings by policy
317
+ @param all_resources: dict of {resource_id: {savings, policy_name, captured_date}}
318
+ @return: dict of {policy_name: total_savings}
319
+ """
320
+ savings_result = {}
321
+
322
+ for resource_id, values in all_resources.items():
323
+ policy_name = values.get('policy_name')
324
+ savings = values.get('savings', 0)
325
+ savings_result[policy_name] = round(savings_result.get(policy_name, 0) + savings, 3)
326
+
327
+ return savings_result
328
+
329
+ def __update_yearly_savings(self, year: int, all_months_data: dict, total_annual_saving: float):
330
+ """
331
+ Update yearly savings in Elasticsearch with all months data.
332
+ Creates a new document if year doesn't exist, or updates existing one.
333
+ @param year: Year (e.g., 2026)
334
+ @param all_months_data: Dictionary of {month_number: savings_value} for all months
335
+ @param total_annual_saving: Total cumulative savings for the year
336
+ @return: True if successful
337
+ """
338
+ try:
339
+ current_date = datetime.now(timezone.utc).date()
340
+ year_id = f"{year}-{self.__account}"
341
+
342
+ data = {
343
+ 'year': year,
344
+ 'total_saving': round(total_annual_saving, 3),
345
+ 'last_updated': current_date.isoformat(),
346
+ 'timestamp': datetime.now(timezone.utc),
347
+ 'policy': 'yearly_savings_report',
348
+ 'index_id': year_id,
349
+ 'account': self.__account
350
+ }
351
+
352
+ for month_num in range(1, 13):
353
+ data[f'month_{month_num}'] = round(all_months_data.get(month_num, 0), 3)
354
+
355
+ try:
356
+ if self.__elastic_operations.verify_elastic_index_doc_id(index=self.__yearly_savings_es_index, doc_id=year_id):
357
+ self.__elastic_operations.update_elasticsearch_index(
358
+ index=self.__yearly_savings_es_index,
359
+ id=year_id,
360
+ metadata=data
361
+ )
362
+ logger.info(f"Updated yearly savings for year {year}")
363
+ else:
364
+ self.__elastic_operations.upload_to_elasticsearch(
365
+ index=self.__yearly_savings_es_index,
366
+ data=data,
367
+ id=year_id
368
+ )
369
+ logger.info(f"Created yearly savings document for year {year}")
370
+ except Exception as e:
371
+ logger.warning(f"Update check failed, trying create: {e}")
372
+ try:
373
+ self.__elastic_operations.upload_to_elasticsearch(
374
+ index=self.__yearly_savings_es_index,
375
+ data=data,
376
+ id=year_id
377
+ )
378
+ logger.info(f"Created yearly savings document for year {year}")
379
+ except Exception as create_err:
380
+ logger.error(f"Failed to create document: {create_err}")
381
+ raise create_err
382
+
383
+ return True
384
+
385
+ except Exception as err:
386
+ logger.error(f"Error updating yearly savings: {err}")
387
+ raise err
388
+
389
+ @logger_time_stamp
390
+ def run(self, start_date: str = None, end_date: str = None):
391
+ """
392
+ Main method to run the yearly savings report
393
+
394
+ @param start_date: Optional start date string (YYYY-MM-DD). If None, checks environment variable, then defaults to Jan 1 of current year.
395
+ @param end_date: Optional end date string (YYYY-MM-DD). If None, checks environment variable, then defaults to today.
396
+ @return: dict with summary
397
+ """
398
+ if not start_date:
399
+ start_date = self.__custom_start_date
400
+ if not end_date:
401
+ end_date = self.__custom_end_date
402
+
403
+ if start_date and end_date:
404
+ try:
405
+ logger.info(f'Using custom date range: {start_date} to {end_date}')
406
+
407
+ month_savings = self.__get_yearly_savings(start_date=start_date, end_date=end_date)
408
+ total_savings = sum(month_savings.values()) if month_savings else 0.0
409
+
410
+ logger.info(f'Custom date range - Policy savings: {month_savings}')
411
+ logger.info(f'Custom date range - Total savings: ${total_savings:,.2f}')
412
+
413
+ return {
414
+ 'status': 'success',
415
+ 'custom_date_range': True,
416
+ 'start_date': start_date,
417
+ 'end_date': end_date,
418
+ 'policy_savings': month_savings,
419
+ 'total_yearly_savings': total_savings
420
+ }
421
+ except ValueError as e:
422
+ logger.error(f'Invalid date format: {e}. Expected YYYY-MM-DD')
423
+ return {'status': 'error', 'message': f'Invalid date format: {e}'}
424
+
425
+ current_date = datetime.now(timezone.utc)
426
+ current_year = current_date.year
427
+ current_month = current_date.month
428
+ today = current_date.date()
429
+
430
+ logger.info(f'Using default date range: current year {current_year}')
431
+
432
+ all_months_data = {}
433
+
434
+ for month in range(1, 13):
435
+ try:
436
+ if month < current_month:
437
+ end_day = self.__get_last_day_of_month(current_year, month)
438
+ month_savings = self.__calculate_month_savings(
439
+ year=current_year,
440
+ month=month,
441
+ start_day=1,
442
+ end_day=end_day
443
+ )
444
+ all_months_data[month] = sum(month_savings.values()) if month_savings else 0.0
445
+
446
+ elif month == current_month:
447
+ month_savings = self.__calculate_month_savings(
448
+ year=current_year,
449
+ month=month,
450
+ start_day=1,
451
+ end_day=today.day
452
+ )
453
+ all_months_data[month] = sum(month_savings.values()) if month_savings else 0.0
454
+
455
+ else:
456
+ all_months_data[month] = 0.0
457
+
458
+ if month < 12:
459
+ time.sleep(0.2)
460
+
461
+ except Exception as e:
462
+ logger.warning(f"Error calculating savings for month {month}: {e}, setting to 0")
463
+ all_months_data[month] = 0.0
464
+
465
+ total_annual_saving = sum(all_months_data.values())
466
+
467
+ logger.info(f'Monthly savings: {all_months_data}')
468
+ logger.info(f'Total annual savings: ${total_annual_saving:,.2f}')
469
+
470
+ if self.__elastic_operations:
471
+ try:
472
+ self.__update_yearly_savings(
473
+ year=current_year,
474
+ all_months_data=all_months_data,
475
+ total_annual_saving=total_annual_saving
476
+ )
477
+ logger.info(f'Successfully uploaded yearly savings to {self.__yearly_savings_es_index}')
478
+ return {
479
+ 'status': 'success',
480
+ 'records_uploaded': 1,
481
+ 'year': current_year,
482
+ 'total_yearly_savings': total_annual_saving,
483
+ 'monthly_savings': all_months_data
484
+ }
485
+ except Exception as err:
486
+ logger.error(f'Error uploading to ES: {err}')
487
+ return {'status': 'error', 'message': str(err)}
488
+ else:
489
+ logger.warning('ES not configured')
490
+ return {'status': 'no_upload', 'message': 'ES not configured'}
@@ -54,7 +54,7 @@ class NonClusterZombiePolicy:
54
54
  self.__email_alert = self.__environment_variables_dict.get(
55
55
  'EMAIL_ALERT') if self.__environment_variables_dict.get('EMAIL_ALERT') else False
56
56
  self.__manager_email_alert = self.__environment_variables_dict.get('MANAGER_EMAIL_ALERT')
57
- self._admins = ['yinsong@redhat.com', 'ebattat@redhat.com']
57
+ self._admins = ['yinsong@redhat.com', 'ebattat@redhat.com', 'pragchau@redhat.com']
58
58
  self._es_upload = ElasticUpload()
59
59
  self.resource_pricing = ResourcesPricing()
60
60
  self._es_operations = ElasticSearchOperations()
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloud-governance
3
- Version: 1.1.402
3
+ Version: 1.1.404
4
4
  Summary: Cloud Governance Tool
5
5
  Home-page: https://github.com/redhat-performance/cloud-governance
6
6
  Author: Red Hat
7
- Author-email: ebattat@redhat.com, athiruma@redhat.com
7
+ Author-email: ebattat@redhat.com, pragchau@redhat.com
8
8
  License: Apache License 2.0
9
9
  Classifier: License :: OSI Approved :: Apache Software License
10
10
  Classifier: Programming Language :: Python :: 3
@@ -178,6 +178,7 @@ cloud_governance/policy/aws/s3_inactive.py
178
178
  cloud_governance/policy/aws/skipped_resources.py
179
179
  cloud_governance/policy/aws/spot_savings_analysis.py
180
180
  cloud_governance/policy/aws/unused_access_key.py
181
+ cloud_governance/policy/aws/yearly_savings_report.py
181
182
  cloud_governance/policy/aws/zombie_cluster_resource.py
182
183
  cloud_governance/policy/aws/zombie_snapshots.py
183
184
  cloud_governance/policy/aws/cleanup/__init__.py
@@ -2,7 +2,7 @@ from codecs import open
2
2
  from os import path
3
3
  from setuptools import setup, find_packages
4
4
 
5
- __version__ = '1.1.402'
5
+ __version__ = '1.1.404'
6
6
 
7
7
  here = path.abspath(path.dirname(__file__))
8
8
 
@@ -19,7 +19,7 @@ setup(
19
19
  long_description=long_description,
20
20
  long_description_content_type='text/markdown',
21
21
  author='Red Hat',
22
- author_email='ebattat@redhat.com, athiruma@redhat.com',
22
+ author_email='ebattat@redhat.com, pragchau@redhat.com',
23
23
  url='https://github.com/redhat-performance/cloud-governance',
24
24
  license="Apache License 2.0",
25
25
  classifiers=[