cid-cmd 4.2.5__tar.gz → 4.2.7__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.
- {cid_cmd-4.2.5/cid_cmd.egg-info → cid_cmd-4.2.7}/PKG-INFO +1 -1
- cid_cmd-4.2.7/cid/_version.py +2 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/common.py +17 -18
- cid_cmd-4.2.7/cid/helpers/parameter_store.py +88 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/quicksight/__init__.py +6 -2
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/quicksight/dataset.py +45 -2
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/utils.py +1 -1
- {cid_cmd-4.2.5 → cid_cmd-4.2.7/cid_cmd.egg-info}/PKG-INFO +1 -1
- cid_cmd-4.2.5/cid/_version.py +0 -2
- cid_cmd-4.2.5/cid/helpers/parameter_store.py +0 -51
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/LICENSE +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/MANIFEST.in +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/README.md +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/__init__.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/base.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/__init__.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/__init__.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/cid/compute.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/cid/ec2_running_cost.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/cid/s3_view.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/cid/summary_view.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/co/dataset.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/cudos/hourly_view.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/cudos/resource_view.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/kpi/kpi_ebs_snap.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/kpi/kpi_ebs_storage_all.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/kpi/kpi_instance_all.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/kpi/kpi_s3_storage_all.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/kpi/kpi_tracker.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/shared/customer_all.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/tao/dataset.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/trends/daily_anomaly_detection.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/trends/monthly_anomaly_detection.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/trends/monthly_bill_by_account.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/permissions/dashboard_permissions.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/permissions/dashboard_permissions_namespace.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/permissions/data_set_permissions.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/permissions/data_source_permissions.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/permissions/folder_permissions.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/cid/compute_savings_plan_eligible_spend.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/cid/ec2_running_cost.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/cid/ri_sp_mapping.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/cid/s3.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/cid/summary_view.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/all_options.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/auto_scale.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/auto_scale_options.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/ebs_volume.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/ebs_volume_options.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/ec2_instance.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/ec2_instance_options.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/ecs_service.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/ecs_service_options.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/idle.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/idle_options.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/lambda.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/lambda_options.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/license.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/license_options.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/rds_database.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/rds_instance_options.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/co/rds_storage_options.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/cudos/hourly_view.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/cudos/resource_view.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/kpi/first_kpi_instance_mapping_view.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/kpi/kpi_ebs_snap_view.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/kpi/kpi_ebs_storage_view.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/kpi/kpi_instance_all_view.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/kpi/kpi_s3_storage_view.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/kpi/last_kpi_tracker_view.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/shared/account_map.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/shared/account_map_cur2.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/shared/account_map_dummy.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/shared/aws_accounts.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/shared/aws_regions.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/shared/aws_service_category_map.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/shared/business_units_map.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/shared/cur.yaml +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/shared/customer_all_unlimited.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/shared/payer_account_name_map.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/shared/ta_descriptions.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/tao/glue_table.json +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/tao/ta_org_view.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/trends/daily_anomaly_detection.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/trends/monthly_anomaly_detection.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/trends/monthly_bill_by_account.sql +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/resources.yaml +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/cli.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/commands/__init__.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/commands/command_base.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/commands/init_qs.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/exceptions.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/export.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/__init__.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/account_map.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/athena.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/cloudformation.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/csv2view.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/cur.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/cur_proxy.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/diff.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/glue.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/iam.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/organizations.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/quicksight/dashboard.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/quicksight/dashboard_patching.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/quicksight/datasource.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/quicksight/definition.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/quicksight/resource.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/quicksight/template.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/quicksight/version.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/randtime.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/s3.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/helpers/timezone.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/logger.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/plugin.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/test/python/test_csv2view.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/test/python/test_isolated_parameters.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/test/python/test_merge.py +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid_cmd.egg-info/SOURCES.txt +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid_cmd.egg-info/dependency_links.txt +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid_cmd.egg-info/entry_points.txt +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid_cmd.egg-info/requires.txt +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid_cmd.egg-info/top_level.txt +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/pyproject.toml +0 -0
- {cid_cmd-4.2.5 → cid_cmd-4.2.7}/setup.cfg +0 -0
|
@@ -282,16 +282,22 @@ class Cid():
|
|
|
282
282
|
export_analysis(self.qs, self.athena, glue=self.glue)
|
|
283
283
|
|
|
284
284
|
def track(self, action, dashboard_id):
|
|
285
|
-
""" Send dashboard_id and account_id to adoption tracker """
|
|
285
|
+
""" Send dashboard_id and account_id to CID adoption tracker """
|
|
286
286
|
method = {'created':'PUT', 'updated':'PATCH', 'deleted': 'DELETE'}.get(action, None)
|
|
287
287
|
if not method:
|
|
288
288
|
logger.debug(f"This will not fail the deployment. Logging action {action} is not supported. This issue will be ignored")
|
|
289
289
|
return
|
|
290
|
-
endpoint = 'https://okakvoavfg.execute-api.eu-west-1.amazonaws.com/'
|
|
290
|
+
endpoint = 'https://okakvoavfg.execute-api.eu-west-1.amazonaws.com/' # AWS Managed
|
|
291
|
+
if os.environ.get('AWS_DEPLOYMENT_TYPE'):
|
|
292
|
+
deployment_type = os.environ.get('AWS_DEPLOYMENT_TYPE')
|
|
293
|
+
elif os.environ.get('AWS_EXECUTION_ENV', '').startswith('AWS_Lambda'):
|
|
294
|
+
deployment_type = 'Lambda'
|
|
295
|
+
else:
|
|
296
|
+
deployment_type = 'CID'
|
|
291
297
|
payload = {
|
|
292
298
|
'dashboard_id': dashboard_id,
|
|
293
299
|
'account_id': self.base.account_id,
|
|
294
|
-
action + '_via':
|
|
300
|
+
action + '_via': deployment_type,
|
|
295
301
|
}
|
|
296
302
|
try:
|
|
297
303
|
res = requests.request(
|
|
@@ -470,17 +476,16 @@ class Cid():
|
|
|
470
476
|
set_defaults(defaults)
|
|
471
477
|
|
|
472
478
|
def dump_default_parameters(self):
|
|
473
|
-
|
|
474
479
|
stop_list = ['profile-name', 'region', 'aws-access-key-id', 'aws-secret-access-key', 'aws-session-token', 'athena-database', 'athena-workgroup']
|
|
475
|
-
current_defaults =
|
|
476
|
-
context=get_parameters().get('dashboard-id')
|
|
477
|
-
)
|
|
478
|
-
current_defaults = current_defaults | get_parameters()
|
|
480
|
+
current_defaults = get_parameters()
|
|
479
481
|
for key in list(current_defaults.keys()):
|
|
480
482
|
if key in stop_list:
|
|
481
483
|
del current_defaults[key]
|
|
482
484
|
logger.trace(f'dumping parameters {current_defaults}')
|
|
483
|
-
self.parameters_controller.dump_parameters(
|
|
485
|
+
self.parameters_controller.dump_parameters(
|
|
486
|
+
current_defaults,
|
|
487
|
+
context=get_parameters().get('dashboard-id')
|
|
488
|
+
)
|
|
484
489
|
|
|
485
490
|
|
|
486
491
|
def ensure_subscription(self):
|
|
@@ -1668,17 +1673,11 @@ class Cid():
|
|
|
1668
1673
|
update_dataset = True
|
|
1669
1674
|
break
|
|
1670
1675
|
|
|
1671
|
-
identical =
|
|
1672
|
-
if isinstance(found_dataset, Dataset):
|
|
1673
|
-
identical = True
|
|
1674
|
-
for key in 'PhysicalTableMap LogicalTableMap OutputColumns ImportMode DataSetUsageConfiguration RowLevelPermissionDataSet FieldFolders RowLevelPermissionTagConfiguration DatasetParameters'.split():
|
|
1675
|
-
if found_dataset.raw.get(key) != compiled_dataset.get(key):
|
|
1676
|
-
logger.trace(f'not identical {key} {found_dataset.raw.get(key)} != {compiled_dataset.get(key)}')
|
|
1677
|
-
identical = False
|
|
1678
|
-
logger.trace(f'identical to existing = {identical}')
|
|
1676
|
+
identical = Dataset.datasets_are_identical(found_dataset, compiled_dataset) # check if dataset needs an update
|
|
1679
1677
|
|
|
1680
1678
|
if update_dataset and not identical:
|
|
1681
|
-
|
|
1679
|
+
merged_dataset = Dataset.merge_datasets(compiled_dataset, found_dataset)
|
|
1680
|
+
self.qs.update_dataset(merged_dataset)
|
|
1682
1681
|
if compiled_dataset.get("ImportMode") == "SPICE":
|
|
1683
1682
|
dataset_id = compiled_dataset.get('DataSetId')
|
|
1684
1683
|
schedules_definitions = []
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
|
|
4
|
+
from cid.exceptions import CidCritical
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
class AthenaStore():
|
|
9
|
+
def __init__(self, athena, view_name='cid_parameters'):
|
|
10
|
+
self.athena = athena
|
|
11
|
+
self.view_name = view_name
|
|
12
|
+
|
|
13
|
+
def dump(self, data):
|
|
14
|
+
''' dump data to athena
|
|
15
|
+
'''
|
|
16
|
+
try:
|
|
17
|
+
# FIXME: make it multi view
|
|
18
|
+
self.athena.query(self._generate_view_query(data, self.view_name))
|
|
19
|
+
except (CidCritical, Exception) as exc:
|
|
20
|
+
logger.debug(f'failed to save parameters store: {exc}')
|
|
21
|
+
|
|
22
|
+
def load(self):
|
|
23
|
+
''' load from athena
|
|
24
|
+
'''
|
|
25
|
+
try:
|
|
26
|
+
res = self.athena.query(f'''select * from {self.view_name}''', include_header=True)
|
|
27
|
+
except CidCritical as exc:
|
|
28
|
+
if 'TABLE_NOT_FOUND' in str(exc):
|
|
29
|
+
res = []
|
|
30
|
+
else:
|
|
31
|
+
raise
|
|
32
|
+
return [{k:v for k, v in zip(res[0], row)} for row in res[1:]]
|
|
33
|
+
|
|
34
|
+
def _to_sql_str(self, val):
|
|
35
|
+
if val is None:
|
|
36
|
+
return "''"
|
|
37
|
+
return "'" + str(val).replace("'", "''") + "'"
|
|
38
|
+
|
|
39
|
+
def _generate_view_query(self, data, name):
|
|
40
|
+
all_keys = {key for dictionary in data for key in dictionary.keys()}
|
|
41
|
+
lines = ',\n '.join([f'''ROW({','.join([self._to_sql_str(line.get(k)) for k in all_keys])})''' for line in data])
|
|
42
|
+
query = f"""
|
|
43
|
+
CREATE OR REPLACE VIEW {name} AS
|
|
44
|
+
SELECT *
|
|
45
|
+
FROM (
|
|
46
|
+
VALUES
|
|
47
|
+
{lines}
|
|
48
|
+
) ignored_table_name ({','.join([key for key in all_keys])})
|
|
49
|
+
"""
|
|
50
|
+
return query
|
|
51
|
+
|
|
52
|
+
class ParametersController(AthenaStore):
|
|
53
|
+
def load_parameters(self, context):
|
|
54
|
+
data = self.load()
|
|
55
|
+
context_parameters = {}
|
|
56
|
+
any_parameters = {}
|
|
57
|
+
# get any context and then override with specific context
|
|
58
|
+
for line in sorted(data, key=lambda x: x.get('date', '')): # latest should override
|
|
59
|
+
any_parameters[line.get('parameter')] = line.get('value')
|
|
60
|
+
if line.get('context') == str(context):
|
|
61
|
+
context_parameters[line.get('parameter')] = line.get('value')
|
|
62
|
+
return any_parameters | context_parameters
|
|
63
|
+
|
|
64
|
+
def dump_parameters(self, params, context=None):
|
|
65
|
+
data = self.load()
|
|
66
|
+
logger.trace(f'loaded parameters {data}')
|
|
67
|
+
params = dict(params)
|
|
68
|
+
date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
69
|
+
|
|
70
|
+
#Update parameters if they are present already
|
|
71
|
+
for line in data:
|
|
72
|
+
for key, val in list(params.items()):
|
|
73
|
+
if line.get('context') == str(context) and line.get('parameter') == key:
|
|
74
|
+
line['value'] = val
|
|
75
|
+
line['date'] = date
|
|
76
|
+
del params[key]
|
|
77
|
+
|
|
78
|
+
#add parameters that are new
|
|
79
|
+
for key, val in list(params.items()):
|
|
80
|
+
data.append({
|
|
81
|
+
'parameter': key,
|
|
82
|
+
'value': ','.join([str(v) for v in val]) if isinstance(val, list) else str(val),
|
|
83
|
+
'context': str(context),
|
|
84
|
+
'date': date
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
logger.trace(f'dumping parameters {data}')
|
|
88
|
+
self.dump(data)
|
|
@@ -261,7 +261,9 @@ class QuickSight(CidBase):
|
|
|
261
261
|
return True
|
|
262
262
|
except self.client.exceptions.AccessDeniedException as exc:
|
|
263
263
|
logger.debug(f'Cannot tag {arn} (AccessDenied).')
|
|
264
|
-
|
|
264
|
+
except self.client.exceptions.ClientError as exc:
|
|
265
|
+
logger.debug(f'Cannot tag {arn} ({exc}).')
|
|
266
|
+
return False
|
|
265
267
|
|
|
266
268
|
|
|
267
269
|
def get_tags(self, arn):
|
|
@@ -733,6 +735,7 @@ class QuickSight(CidBase):
|
|
|
733
735
|
'AwsAccountId': self.account_id,
|
|
734
736
|
'DashboardId': dashboard_id
|
|
735
737
|
}
|
|
738
|
+
logger.debug(f'describe_dashboard_definition({dashboard_id})')
|
|
736
739
|
result = self.client.describe_dashboard_definition(**parameters)
|
|
737
740
|
self._definitions.update({f'{self.account_id}:{self.identityRegion}:{dashboard_id}': CidQsDefinition(result.get('Definition'))})
|
|
738
741
|
logger.debug(result)
|
|
@@ -1287,6 +1290,7 @@ class QuickSight(CidBase):
|
|
|
1287
1290
|
'DashboardId': definition.get('dashboardId'),
|
|
1288
1291
|
'VersionNumber': created_version
|
|
1289
1292
|
}
|
|
1293
|
+
logger.debug(f"describe_dashboard { definition.get('dashboardId')}")
|
|
1290
1294
|
dashboard = self.describe_dashboard(poll=True, **describe_parameters)
|
|
1291
1295
|
logger.debug('dashboard={dashboard}')
|
|
1292
1296
|
self.set_tags(dashboard.arn, cid_version_tag=dashboard.cid_version) # try to update version tag
|
|
@@ -1304,7 +1308,7 @@ class QuickSight(CidBase):
|
|
|
1304
1308
|
definition: cid dashboard definition. NOT QS DEFINITION.
|
|
1305
1309
|
returns: what we need tof create or update API
|
|
1306
1310
|
"""
|
|
1307
|
-
|
|
1311
|
+
cid_print('Preparing dashboard definition')
|
|
1308
1312
|
create_parameters = {
|
|
1309
1313
|
'AwsAccountId': self.account_id,
|
|
1310
1314
|
'DashboardId': definition.get('dashboardId'),
|
|
@@ -8,6 +8,12 @@ from cid.helpers.quicksight.resource import CidQsResource
|
|
|
8
8
|
|
|
9
9
|
logger = logging.getLogger(__name__)
|
|
10
10
|
|
|
11
|
+
DATASET_PROPERTIES = [
|
|
12
|
+
'AwsAccountId', 'DataSetId', 'Name', 'PhysicalTableMap', 'LogicalTableMap', 'ImportMode', 'ColumnGroups',
|
|
13
|
+
'RowLevelPermissionDataSet', 'RowLevelPermissionTagConfiguration', 'FieldFolders', 'ColumnLevelPermissionRules',
|
|
14
|
+
'DataSetUsageConfiguration', 'DatasetParameters', 'PerformanceConfiguration'
|
|
15
|
+
]
|
|
16
|
+
|
|
11
17
|
|
|
12
18
|
class Dataset(CidQsResource):
|
|
13
19
|
|
|
@@ -189,7 +195,7 @@ class Dataset(CidQsResource):
|
|
|
189
195
|
projected_cols.append(col)
|
|
190
196
|
|
|
191
197
|
# filter out all columns that cannot be used for dataset creation
|
|
192
|
-
update_ = {key: value for key, value in dataset.items() if key in
|
|
198
|
+
update_ = {key: value for key, value in dataset.items() if key in DATASET_PROPERTIES}
|
|
193
199
|
logger.trace(f'update_ = {update_}')
|
|
194
200
|
return update_
|
|
195
201
|
|
|
@@ -230,4 +236,41 @@ class Dataset(CidQsResource):
|
|
|
230
236
|
for alias, join in join_clauses.items():
|
|
231
237
|
if isinstance(data['Data'].get(alias), dict) :
|
|
232
238
|
data['Data'][alias]['clause'] = join
|
|
233
|
-
return (yaml.safe_dump(data))
|
|
239
|
+
return (yaml.safe_dump(data))
|
|
240
|
+
|
|
241
|
+
@staticmethod
|
|
242
|
+
def datasets_are_identical(dataset1, dataset2):
|
|
243
|
+
''' Compare 2 datasets and returns True if no difference found
|
|
244
|
+
'''
|
|
245
|
+
if (not dataset1 and not dataset2):
|
|
246
|
+
return True
|
|
247
|
+
identical = False
|
|
248
|
+
if (dataset1 and not dataset2) or (not dataset1 and dataset2):
|
|
249
|
+
return identical
|
|
250
|
+
dataset1 = dataset1 if isinstance(dataset1, Dataset) else Dataset(dataset1)
|
|
251
|
+
dataset2 = dataset2 if isinstance(dataset2, Dataset) else Dataset(dataset2)
|
|
252
|
+
identical = True
|
|
253
|
+
for key in DATASET_PROPERTIES:
|
|
254
|
+
if key in ['AwsAccountId', 'DataSetId']:
|
|
255
|
+
continue
|
|
256
|
+
if dataset1.raw.get(key) != dataset2.raw.get(key):
|
|
257
|
+
logger.trace(f'not identical {key} {dataset1.raw.get(key)} != {dataset2.raw.get(key)}')
|
|
258
|
+
identical = False
|
|
259
|
+
logger.trace(f'identical to existing = {identical}')
|
|
260
|
+
return identical
|
|
261
|
+
|
|
262
|
+
@staticmethod
|
|
263
|
+
def merge_datasets(dataset1, dataset2):
|
|
264
|
+
''' merge high level 2 datasets. Not a deep merge.
|
|
265
|
+
'''
|
|
266
|
+
if not dataset2:
|
|
267
|
+
return dataset1
|
|
268
|
+
if not dataset1:
|
|
269
|
+
return dataset2
|
|
270
|
+
dataset1 = dataset1 if isinstance(dataset1, Dataset) else Dataset(dataset1)
|
|
271
|
+
dataset2 = dataset2 if isinstance(dataset2, Dataset) else Dataset(dataset2)
|
|
272
|
+
result = {}
|
|
273
|
+
for key in DATASET_PROPERTIES:
|
|
274
|
+
if dataset1.raw.get(key) or dataset2.raw.get(key):
|
|
275
|
+
result[key] = dataset1.raw.get(key) or dataset2.raw.get(key)
|
|
276
|
+
return result
|
|
@@ -276,7 +276,7 @@ def get_parameter(param_name, message, choices=None, default=None, none_as_disab
|
|
|
276
276
|
if multi:
|
|
277
277
|
default = default or []
|
|
278
278
|
default = default if isinstance(default, list) else [default]
|
|
279
|
-
default = [c for c in
|
|
279
|
+
default = [c for c in default if c in choices]
|
|
280
280
|
if not isatty():
|
|
281
281
|
result = default
|
|
282
282
|
else:
|
cid_cmd-4.2.5/cid/_version.py
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
from cid.exceptions import CidCritical
|
|
2
|
-
|
|
3
|
-
class AthenaStore():
|
|
4
|
-
def __init__(self, athena, view_name='cid_parameters'):
|
|
5
|
-
self.athena = athena
|
|
6
|
-
self.view_name = view_name
|
|
7
|
-
|
|
8
|
-
def dump(self, data):
|
|
9
|
-
''' load from athena
|
|
10
|
-
'''
|
|
11
|
-
# FIXME: make it multi view
|
|
12
|
-
self.athena.query(self._generate_view_query(data, self.view_name))
|
|
13
|
-
|
|
14
|
-
def load(self):
|
|
15
|
-
''' load from athena
|
|
16
|
-
'''
|
|
17
|
-
try:
|
|
18
|
-
res = self.athena.query(f'''select * from {self.view_name}''', include_header=True)
|
|
19
|
-
except CidCritical as exc:
|
|
20
|
-
if 'TABLE_NOT_FOUND' in str(exc):
|
|
21
|
-
res = []
|
|
22
|
-
else:
|
|
23
|
-
raise
|
|
24
|
-
return [{k:v for k, v in zip(res[0], row)} for row in res[1:]]
|
|
25
|
-
|
|
26
|
-
def _to_sql_str(self, val):
|
|
27
|
-
if val is None:
|
|
28
|
-
return "''"
|
|
29
|
-
return "'" + str(val).replace("'", "''") + "'"
|
|
30
|
-
|
|
31
|
-
def _generate_view_query(self, data, name):
|
|
32
|
-
all_keys = {key for dictionary in data for key in dictionary.keys()}
|
|
33
|
-
lines = ',\n '.join([f'''ROW({','.join([self._to_sql_str(line.get(k)) for k in all_keys])})''' for line in data])
|
|
34
|
-
query = f"""
|
|
35
|
-
CREATE OR REPLACE VIEW {name} AS
|
|
36
|
-
SELECT *
|
|
37
|
-
FROM (
|
|
38
|
-
VALUES
|
|
39
|
-
{lines}
|
|
40
|
-
) ignored_table_name ({','.join([key for key in all_keys])})
|
|
41
|
-
"""
|
|
42
|
-
return query
|
|
43
|
-
|
|
44
|
-
class ParametersController(AthenaStore):
|
|
45
|
-
def load_parameters(self, context):
|
|
46
|
-
data = self.load()
|
|
47
|
-
return { line.get('parameter'):line.get('value') for line in data}
|
|
48
|
-
|
|
49
|
-
def dump_parameters(self, params, context=None):
|
|
50
|
-
data = [{'parameter': key, 'value': ','.join(val) if isinstance(val, list) else val, 'context': str(context) } for key, val in params.items()]
|
|
51
|
-
self.dump(data)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/trends/daily_anomaly_detection.json
RENAMED
|
File without changes
|
{cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/trends/monthly_anomaly_detection.json
RENAMED
|
File without changes
|
{cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/datasets/trends/monthly_bill_by_account.json
RENAMED
|
File without changes
|
{cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/permissions/dashboard_permissions.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/permissions/data_source_permissions.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/shared/aws_service_category_map.sql
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/shared/customer_all_unlimited.sql
RENAMED
|
File without changes
|
{cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/shared/payer_account_name_map.sql
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/trends/daily_anomaly_detection.sql
RENAMED
|
File without changes
|
{cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/trends/monthly_anomaly_detection.sql
RENAMED
|
File without changes
|
{cid_cmd-4.2.5 → cid_cmd-4.2.7}/cid/builtin/core/data/queries/trends/monthly_bill_by_account.sql
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|