kaqing 2.0.28__tar.gz → 2.0.30__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.
- {kaqing-2.0.28 → kaqing-2.0.30}/PKG-INFO +1 -1
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/alter_tables.py +4 -20
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/command.py +0 -1
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/cql_utils.py +45 -1
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/cqlsh.py +1 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/deploy/deploy_pod.py +7 -2
- kaqing-2.0.30/adam/commands/describe_keyspace.py +63 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/login.py +1 -1
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/param_set.py +1 -1
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/config.py +1 -1
- kaqing-2.0.30/adam/embedded_params.py +2 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/cassandra_nodes.py +1 -1
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/kube_context.py +1 -1
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/repl.py +5 -5
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/repl_commands.py +2 -1
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/utils.py +13 -0
- kaqing-2.0.30/adam/version.py +5 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/kaqing.egg-info/PKG-INFO +1 -1
- {kaqing-2.0.28 → kaqing-2.0.30}/kaqing.egg-info/SOURCES.txt +1 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/setup.py +1 -1
- kaqing-2.0.28/adam/embedded_params.py +0 -2
- kaqing-2.0.28/adam/version.py +0 -5
- {kaqing-2.0.28 → kaqing-2.0.30}/README +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/__init__.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/app_session.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/apps.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/batch.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/checks/__init__.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/checks/check.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/checks/check_context.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/checks/check_result.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/checks/check_utils.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/checks/compactionstats.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/checks/cpu.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/checks/disk.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/checks/gossip.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/checks/issue.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/checks/memory.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/checks/status.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/cli.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/cli_group.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/__init__.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/column.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/columns.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/compactions.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/cpu.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/dir_data.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/dir_snapshots.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/gossip.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/host_id.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/memory.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/node_address.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/node_load.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/node_owns.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/node_status.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/node_tokens.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/node_utils.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/pod_name.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/volume_cassandra.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/columns/volume_root.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/__init__.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/app.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/app_ping.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/bash.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/cd.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/check.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/cli_commands.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/command_helpers.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/commands_utils.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/cp.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/deploy/__init__.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/deploy/code_start.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/deploy/code_stop.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/deploy/code_utils.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/deploy/deploy.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/deploy/deploy_frontend.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/deploy/deploy_pg_agent.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/deploy/deploy_utils.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/deploy/undeploy.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/deploy/undeploy_frontend.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/deploy/undeploy_pg_agent.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/deploy/undeploy_pod.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/devices.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/exit.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/help.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/issues.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/logs.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/ls.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/medusa/__init__.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/medusa/medusa.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/medusa/medusa_backup.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/medusa/medusa_restore.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/medusa/medusa_show_backupjobs.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/medusa/medusa_show_restorejobs.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/nodetool.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/nodetool_commands.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/param_get.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/postgres/__init__.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/postgres/postgres.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/postgres/postgres_ls.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/postgres/postgres_preview.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/postgres/postgres_session.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/preview_table.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/pwd.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/reaper/__init__.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/reaper/reaper.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/reaper/reaper_forward.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/reaper/reaper_forward_stop.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/reaper/reaper_restart.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/reaper/reaper_run_abort.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/reaper/reaper_runs.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/reaper/reaper_runs_abort.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/reaper/reaper_schedule_activate.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/reaper/reaper_schedule_start.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/reaper/reaper_schedule_stop.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/reaper/reaper_schedules.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/reaper/reaper_session.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/reaper/reaper_status.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/repair/__init__.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/repair/repair.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/repair/repair_log.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/repair/repair_run.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/repair/repair_scan.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/repair/repair_stop.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/report.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/restart.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/rollout.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/shell.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/show/__init__.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/show/show.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/show/show_adam.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/show/show_app_actions.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/show/show_app_id.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/show/show_app_queues.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/show/show_cassandra_status.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/show/show_cassandra_version.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/show/show_commands.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/show/show_login.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/show/show_params.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/show/show_processes.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/show/show_repairs.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/show/show_storage.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/commands/watch.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/embedded_apps.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/__init__.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/cassandra_clusters.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/config_maps.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/custom_resources.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/deployment.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/ingresses.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/jobs.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/pods.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/secrets.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/service_accounts.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/services.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/statefulsets.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/k8s_utils/volumes.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/log.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/pod_exec_result.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/repl_session.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/repl_state.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/sso/__init__.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/sso/authenticator.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/sso/authn_ad.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/sso/authn_okta.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/sso/cred_cache.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/sso/id_token.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/sso/idp.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/sso/idp_login.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/sso/idp_session.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/adam/sso/sso_config.py +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/kaqing.egg-info/dependency_links.txt +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/kaqing.egg-info/entry_points.txt +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/kaqing.egg-info/top_level.txt +0 -0
- {kaqing-2.0.28 → kaqing-2.0.30}/setup.cfg +0 -0
@@ -54,7 +54,7 @@ class AlterTables(Command):
|
|
54
54
|
|
55
55
|
excludes = [e.strip(' \r\n') for e in Config().get(
|
56
56
|
'cql.alter-tables.excludes',
|
57
|
-
'system_auth,system_traces,system_distributed,system_views,system,system_schema,system_virtual_schema').split(',')]
|
57
|
+
'system_auth,system_traces,reaper_db,system_distributed,system_views,system,system_schema,system_virtual_schema').split(',')]
|
58
58
|
batching = Config().get('cql.alter-tables.batching', True)
|
59
59
|
tables = parse_cql_desc_tables(r[0].stdout)
|
60
60
|
for k, v in tables.items():
|
@@ -63,7 +63,7 @@ class AlterTables(Command):
|
|
63
63
|
# alter table <table_name> with GC_GRACE_SECONDS = <timeout>;
|
64
64
|
cql = ';\n'.join([f'alter table {k}.{t} with {arg_str}' for t in v])
|
65
65
|
try:
|
66
|
-
run_cql(state, cql, [], show_out=Config().
|
66
|
+
run_cql(state, cql, [], show_out=Config().is_debug(), on_any=True)
|
67
67
|
except Exception as e:
|
68
68
|
log2(e)
|
69
69
|
continue
|
@@ -72,7 +72,7 @@ class AlterTables(Command):
|
|
72
72
|
try:
|
73
73
|
# alter table <table_name> with GC_GRACE_SECONDS = <timeout>;
|
74
74
|
cql = f'alter table {k}.{t} with {arg_str}'
|
75
|
-
run_cql(state, cql, [], show_out=Config().
|
75
|
+
run_cql(state, cql, [], show_out=Config().is_debug(), on_any=True)
|
76
76
|
except Exception as e:
|
77
77
|
log2(e)
|
78
78
|
continue
|
@@ -92,20 +92,4 @@ class AlterTables(Command):
|
|
92
92
|
return {}
|
93
93
|
|
94
94
|
def help(self, _: ReplState) -> str:
|
95
|
-
return f'
|
96
|
-
|
97
|
-
class CqlCommandHelper(click.Command):
|
98
|
-
def get_help(self, ctx: click.Context):
|
99
|
-
log(super().get_help(ctx))
|
100
|
-
log()
|
101
|
-
log(' e.g. qing cql <cluster or pod> select host_id from system.local')
|
102
|
-
log()
|
103
|
-
log('Advanced Usages:')
|
104
|
-
log(' 1. Use -- to specify what arguments are passed to the cqlsh.')
|
105
|
-
log(' 2. Use "" to avoid expansion on shell variables.')
|
106
|
-
log(' 3. Use ; to use multiple CQL statements')
|
107
|
-
log()
|
108
|
-
log(' e.g. qing cql <cluster or pod> -- "consistency quorum; select * from system.local" --request-timeout=3600')
|
109
|
-
log()
|
110
|
-
|
111
|
-
ClusterOrPodCommandHelper.cluter_or_pod_help()
|
95
|
+
return f'{AlterTables.COMMAND} <param = value> [--include-reaper] \t alter on all tables'
|
@@ -1,9 +1,24 @@
|
|
1
|
+
import functools
|
1
2
|
import re
|
2
3
|
|
3
4
|
from adam.k8s_utils.cassandra_clusters import CassandraClusters
|
4
5
|
from adam.k8s_utils.cassandra_nodes import CassandraNodes
|
5
6
|
from adam.k8s_utils.secrets import Secrets
|
7
|
+
from adam.pod_exec_result import PodExecResult
|
6
8
|
from adam.repl_state import ReplState
|
9
|
+
from adam.utils import log2
|
10
|
+
|
11
|
+
@functools.lru_cache()
|
12
|
+
def keyspaces(sts: str, namespace: str):
|
13
|
+
user, pw = Secrets.get_user_pass(sts, namespace, secret_path='cql.secret')
|
14
|
+
command = f'cqlsh -u {user} -p {pw} -e "describe keyspaces"'
|
15
|
+
|
16
|
+
r: list[PodExecResult] = CassandraClusters.exec(sts, namespace, command, show_out=False, action='cql', on_any=True)
|
17
|
+
if not r:
|
18
|
+
log2('No pod is available')
|
19
|
+
return []
|
20
|
+
|
21
|
+
return parse_cql_desc_keyspaces(r[0].stdout)
|
7
22
|
|
8
23
|
def run_cql(state: ReplState, cql: str, opts: list = [], show_out = False, use_single_quotes = False, on_any = False):
|
9
24
|
user, pw = Secrets.get_user_pass(state.sts if state.sts else state.pod, state.namespace, secret_path='cql.secret')
|
@@ -50,4 +65,33 @@ def parse_cql_desc_tables(out: str):
|
|
50
65
|
tables_by_keyspace[keyspace] = []
|
51
66
|
tables_by_keyspace[keyspace].append(t)
|
52
67
|
|
53
|
-
return tables_by_keyspace
|
68
|
+
return tables_by_keyspace
|
69
|
+
|
70
|
+
def parse_cql_desc_keyspaces(out: str) -> list[str]:
|
71
|
+
#
|
72
|
+
# Warning: Cannot create directory at `/home/cassandra/.cassandra`. Command history will not be saved. Please check what was the environment property CQL_HISTORY set to.
|
73
|
+
#
|
74
|
+
#
|
75
|
+
# Warning: Using a password on the command line interface can be insecure.
|
76
|
+
# Recommendation: use the credentials file to securely provide the password.
|
77
|
+
#
|
78
|
+
#
|
79
|
+
# azops88_db system_auth system_traces
|
80
|
+
# reaper_db system_distributed system_views
|
81
|
+
# system system_schema system_virtual_schema
|
82
|
+
#
|
83
|
+
kses = []
|
84
|
+
for line in out.split('\n'):
|
85
|
+
line = line.strip(' \r')
|
86
|
+
if not line:
|
87
|
+
continue
|
88
|
+
if line.startswith('Warning:'):
|
89
|
+
continue
|
90
|
+
if line.startswith('Recommendation:'):
|
91
|
+
continue
|
92
|
+
|
93
|
+
for ks in line.split(' '):
|
94
|
+
if s := ks.strip(' \r\t'):
|
95
|
+
kses.append(s)
|
96
|
+
|
97
|
+
return kses
|
@@ -3,6 +3,7 @@ import yaml
|
|
3
3
|
|
4
4
|
from adam.commands.command import Command
|
5
5
|
from adam.commands.deploy.deploy_utils import creating, deploy_frontend, gen_labels
|
6
|
+
from adam.commands.deploy.undeploy_pod import UndeployPod
|
6
7
|
from adam.config import Config
|
7
8
|
from adam.k8s_utils.config_maps import ConfigMaps
|
8
9
|
from adam.k8s_utils.deployment import Deployments
|
@@ -39,6 +40,10 @@ class DeployPod(Command):
|
|
39
40
|
if not self.validate_state(state):
|
40
41
|
return state
|
41
42
|
|
43
|
+
args, forced = Command.extract_options(args, '--force')
|
44
|
+
if forced:
|
45
|
+
UndeployPod().run(UndeployPod.COMMAND, state)
|
46
|
+
|
42
47
|
if KubeContext.in_cluster():
|
43
48
|
log2('This is doable only from outside of the Kubernetes cluster.')
|
44
49
|
return state
|
@@ -103,7 +108,7 @@ class DeployPod(Command):
|
|
103
108
|
return state
|
104
109
|
|
105
110
|
def completion(self, state: ReplState):
|
106
|
-
return super().completion(state)
|
111
|
+
return super().completion(state, {'--force': None})
|
107
112
|
|
108
113
|
def help(self, _: ReplState):
|
109
|
-
return f'{DeployPod.COMMAND}\t deploy Ops pod'
|
114
|
+
return f'{DeployPod.COMMAND} [--force]\t deploy Ops pod, --force to undeploy first'
|
@@ -0,0 +1,63 @@
|
|
1
|
+
import click
|
2
|
+
|
3
|
+
from adam.commands.command import Command
|
4
|
+
from adam.commands.command_helpers import ClusterOrPodCommandHelper
|
5
|
+
from adam.commands.cql_utils import keyspaces, parse_cql_desc_tables, run_cql
|
6
|
+
from adam.config import Config
|
7
|
+
from adam.pod_exec_result import PodExecResult
|
8
|
+
from adam.repl_state import ReplState, RequiredState
|
9
|
+
from adam.utils import log, log2
|
10
|
+
|
11
|
+
class DescribeKeyspace(Command):
|
12
|
+
COMMAND = 'describe keyspace'
|
13
|
+
|
14
|
+
# the singleton pattern
|
15
|
+
def __new__(cls, *args, **kwargs):
|
16
|
+
if not hasattr(cls, 'instance'): cls.instance = super(DescribeKeyspace, cls).__new__(cls)
|
17
|
+
|
18
|
+
return cls.instance
|
19
|
+
|
20
|
+
def __init__(self, successor: Command=None):
|
21
|
+
super().__init__(successor)
|
22
|
+
|
23
|
+
def required(self):
|
24
|
+
return RequiredState.CLUSTER
|
25
|
+
|
26
|
+
def command(self):
|
27
|
+
return DescribeKeyspace.COMMAND
|
28
|
+
|
29
|
+
def run(self, cmd: str, state: ReplState):
|
30
|
+
if not(args := self.args(cmd)):
|
31
|
+
return super().run(cmd, state)
|
32
|
+
|
33
|
+
state, args = self.apply_state(args, state)
|
34
|
+
if not self.validate_state(state):
|
35
|
+
return state
|
36
|
+
|
37
|
+
if not args:
|
38
|
+
if state.in_repl:
|
39
|
+
log2('Please enter keyspace name')
|
40
|
+
else:
|
41
|
+
log2('* keyspace name is missing.')
|
42
|
+
log2()
|
43
|
+
Command.display_help()
|
44
|
+
|
45
|
+
return 'missing-keyspace'
|
46
|
+
|
47
|
+
r: list[PodExecResult] = run_cql(state, f'describe keyspace {args[0]}', show_out=True, on_any=True)
|
48
|
+
if not r:
|
49
|
+
log2('No pod is available')
|
50
|
+
return 'no-pod'
|
51
|
+
|
52
|
+
# do not continue to cql route
|
53
|
+
return state
|
54
|
+
|
55
|
+
def completion(self, state: ReplState) -> dict[str, any]:
|
56
|
+
if state.sts:
|
57
|
+
state.wait_log("Inspecting Cassandra Keyspaces...")
|
58
|
+
return super().completion(state, {ks: None for ks in keyspaces(state.sts, state.namespace)})
|
59
|
+
|
60
|
+
return {}
|
61
|
+
|
62
|
+
def help(self, _: ReplState) -> str:
|
63
|
+
return f'{DescribeKeyspace.COMMAND} <keyspace-name>\t describe Cassandra keyspace'
|
@@ -38,7 +38,7 @@ class Login(Command):
|
|
38
38
|
state, args = self.apply_state(args, state)
|
39
39
|
args, debug = Command.extract_options(args, ['d'])
|
40
40
|
if debug:
|
41
|
-
Config().set('debug
|
41
|
+
Config().set('debug', True)
|
42
42
|
|
43
43
|
username: str = os.getenv('USERNAME')
|
44
44
|
if len(args) > 0:
|
@@ -38,7 +38,7 @@ class SetParam(Command):
|
|
38
38
|
return value
|
39
39
|
|
40
40
|
def completion(self, _: ReplState):
|
41
|
-
return {SetParam.COMMAND: {key: None for key in Config().keys()}}
|
41
|
+
return {SetParam.COMMAND: {key: ({'true': None, 'false': None} if Config().get(key, None) in [True, False] else None) for key in Config().keys()}}
|
42
42
|
|
43
43
|
def help(self, _: ReplState):
|
44
44
|
return f"{SetParam.COMMAND} <key> <value>\t sets a Kaqing parameter to a different value"
|
@@ -0,0 +1,2 @@
|
|
1
|
+
def config():
|
2
|
+
return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'bash': {'workers': 32}, 'cassandra': {'service-name': 'all-pods-service'}, 'cql': {'workers': 32, 'samples': 3, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-superuser', 'password-item': 'password'}, 'alter-tables': {'excludes': 'system_auth,system_traces,reaper_db,system_distributed,system_views,system,system_schema,system_virtual_schema', 'gc-grace-periods': '3600,86400,864000,7776000', 'batching': True}}, 'checks': {'compactions-threshold': 250, 'cpu-busy-threshold': 98.0, 'cpu-threshold': 0.0, 'cassandra-data-path': '/c3/cassandra', 'root-disk-threshold': 50, 'cassandra-disk-threshold': 50, 'snapshot-size-cmd': "ls /c3/cassandra/data/data/*/*/snapshots | grep snapshots | sed 's/:$//g' | xargs -I {} du -sk {} | awk '{print $1}' | awk '{s+=$1} END {print s}'", 'snapshot-size-threshold': '40G', 'table-sizes-cmd': "ls -Al /c3/cassandra/data/data/ | awk '{print $9}' | sed 's/\\^r//g' | xargs -I {} du -sk /c3/cassandra/data/data/{}"}, 'get-host-id': {'workers': 32}, 'idps': {'ad': {'email-pattern': '.*@c3.ai', 'uri': 'https://login.microsoftonline.com/53ad779a-93e7-485c-ba20-ac8290d7252b/oauth2/v2.0/authorize?response_type=id_token&response_mode=form_post&client_id=00ff94a8-6b0a-4715-98e0-95490012d818&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fplat.c3ci.cloud%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://login.microsoftonline.com/common/discovery/keys', 'contact': 'Please contact ted.tran@c3.ai.', 'whitelist-file': '/kaqing/members'}, 'okta': {'default': True, 'email-pattern': '.*@c3iot.com', 'uri': 'https://c3energy.okta.com/oauth2/v1/authorize?response_type=id_token&response_mode=form_post&client_id={client_id}&scope=openid+email+profile+groups&redirect_uri=https%3A%2F%2F{host}%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://c3energy.okta.com/oauth2/v1/keys'}}, 'issues': {'workers': 32}, 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'medusa': {'restore-auto-complete': False}, 'nodetool': {'workers': 32, 'samples': 3, 'commands_in_line': 40}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu,mem', 'header': 'POD_NAME,CPU,MEM/LIMIT'}, 'reaper': {'service-name': 'reaper-service', 'port-forward': {'timeout': 86400, 'local-port': 9001}, 'abort-runs-batch': 10, 'show-runs-batch': 100, 'pod': {'cluster-regex': '(.*?-.*?-.*?-.*?)-.*', 'label-selector': 'k8ssandra.io/reaper={cluster}-reaper'}, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-reaper-ui', 'password-item': 'password'}}, 'repair': {'log-path': '/home/cassrepair/logs/', 'image': 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.14', 'secret': 'ciregistryc3iotio', 'env': {'interval': 24, 'timeout': 60, 'pr': False, 'runs': 1}}, 'repl': {'start-drive': 'a', 'auto-enter-app': 'c3/c3', 'auto-enter-only-cluster': True}, 'status': {'columns': 'status,address,load,tokens,owns,host_id,gossip,compactions', 'header': '--,Address,Load,Tokens,Owns,Host ID,GOSSIP,COMPACTIONS'}, 'storage': {'columns': 'pod,volume_root,volume_cassandra,snapshots,data,compactions', 'header': 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS'}, 'watch': {'auto': 'rollout', 'timeout': 3600, 'interval': 10}, 'debug': False, 'debugs': {'timings': False, 'exit-on-error': False, 'show-parallelism': False}}
|
@@ -12,7 +12,7 @@ class CassandraNodes:
|
|
12
12
|
try:
|
13
13
|
user, pw = Secrets.get_user_pass(pod_name, ns)
|
14
14
|
command = f'echo "SELECT host_id FROM system.local; exit" | cqlsh --no-color -u {user} -p {pw}'
|
15
|
-
result: PodExecResult = CassandraNodes.exec(pod_name, ns, command, show_out=Config().
|
15
|
+
result: PodExecResult = CassandraNodes.exec(pod_name, ns, command, show_out=Config().is_debug())
|
16
16
|
next = False
|
17
17
|
for line in result.stdout.splitlines():
|
18
18
|
if next:
|
@@ -18,7 +18,7 @@ from adam.log import Log
|
|
18
18
|
from adam.repl_commands import ReplCommands
|
19
19
|
from adam.repl_session import ReplSession
|
20
20
|
from adam.repl_state import ReplState
|
21
|
-
from adam.utils import deep_merge_dicts, lines_to_tabular, log2
|
21
|
+
from adam.utils import deep_merge_dicts, deep_sort_dict, lines_to_tabular, log2
|
22
22
|
from adam.apps import Apps
|
23
23
|
from . import __version__
|
24
24
|
|
@@ -102,9 +102,9 @@ def enter_repl(state: ReplState):
|
|
102
102
|
for cmd in sorted_cmds:
|
103
103
|
s1 = time.time()
|
104
104
|
try:
|
105
|
-
completions = deep_merge_dicts(completions, cmd.completion(state))
|
105
|
+
completions = deep_sort_dict(deep_merge_dicts(completions, cmd.completion(state)))
|
106
106
|
finally:
|
107
|
-
if Config().get('
|
107
|
+
if Config().get('debugs.timings', False):
|
108
108
|
Config().debug('Timing completion calc', cmd.command(), f'{time.time() - s1:.2f}')
|
109
109
|
|
110
110
|
completer = NestedCompleter.from_nested_dict(completions)
|
@@ -145,14 +145,14 @@ def enter_repl(state: ReplState):
|
|
145
145
|
except EOFError: # Handle Ctrl+D (EOF) for graceful exit
|
146
146
|
break
|
147
147
|
except Exception as e:
|
148
|
-
if Config().get('
|
148
|
+
if Config().get('debugs.exit-on-error', False):
|
149
149
|
raise e
|
150
150
|
else:
|
151
151
|
log2(e)
|
152
152
|
Config().debug(traceback.format_exc())
|
153
153
|
finally:
|
154
154
|
state.clear_wait_log_flag()
|
155
|
-
if Config().get('
|
155
|
+
if Config().get('debugs.timings', False) and 'cmd' in locals() and 's0' in locals():
|
156
156
|
print('Timing command', cmd, f'{time.time() - s0:.2f}')
|
157
157
|
|
158
158
|
@cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=ClusterCommandHelper, help="Enter interactive shell.")
|
@@ -11,6 +11,7 @@ from adam.commands.deploy.undeploy import Undeploy
|
|
11
11
|
from adam.commands.deploy.undeploy_frontend import UndeployFrontend
|
12
12
|
from adam.commands.deploy.undeploy_pg_agent import UndeployPgAgent
|
13
13
|
from adam.commands.deploy.undeploy_pod import UndeployPod
|
14
|
+
from adam.commands.describe_keyspace import DescribeKeyspace
|
14
15
|
from adam.commands.shell import Shell
|
15
16
|
from adam.commands.show.show_app_queues import ShowAppQueues
|
16
17
|
from adam.commands.cp import ClipboardCopy
|
@@ -75,7 +76,7 @@ class ReplCommands:
|
|
75
76
|
GetParam(), SetParam(), ShowParams(), ShowKubectlCommands(), ShowLogin(), ShowAdam()]
|
76
77
|
|
77
78
|
def cassandra_check() -> list[Command]:
|
78
|
-
return [ShowCassandraStatus(), ShowCassandraVersion(), ShowRepairs(), ShowStorage(), ShowProcesses(), Check(), Issues(), NodeTool(), Report()]
|
79
|
+
return [DescribeKeyspace(), ShowCassandraStatus(), ShowCassandraVersion(), ShowRepairs(), ShowStorage(), ShowProcesses(), Check(), Issues(), NodeTool(), Report()]
|
79
80
|
|
80
81
|
def cassandra_ops() -> list[Command]:
|
81
82
|
# return Medusa.cmd_list() + [Restart(), RollOut(), Watch()] + Reaper.cmd_list() + Repair.cmd_list()
|
@@ -125,6 +125,19 @@ def deep_merge_dicts(dict1, dict2):
|
|
125
125
|
merged_dict[key] = value
|
126
126
|
return merged_dict
|
127
127
|
|
128
|
+
def deep_sort_dict(d):
|
129
|
+
"""
|
130
|
+
Recursively sorts a dictionary by its keys, and any nested lists by their elements.
|
131
|
+
"""
|
132
|
+
if not isinstance(d, (dict, list)):
|
133
|
+
return d
|
134
|
+
|
135
|
+
if isinstance(d, dict):
|
136
|
+
return {k: deep_sort_dict(d[k]) for k in sorted(d)}
|
137
|
+
|
138
|
+
if isinstance(d, list):
|
139
|
+
return sorted([deep_sort_dict(item) for item in d])
|
140
|
+
|
128
141
|
def get_deep_keys(d, current_path=""):
|
129
142
|
"""
|
130
143
|
Recursively collects all combined keys (paths) from a deep dictionary.
|
@@ -1,2 +0,0 @@
|
|
1
|
-
def config():
|
2
|
-
return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'bash': {'workers': 32}, 'cassandra': {'service-name': 'all-pods-service'}, 'cql': {'workers': 32, 'samples': 3, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-superuser', 'password-item': 'password'}, 'alter-tables': {'excludes': 'system_auth,system_traces,system_distributed,system_views,system,system_schema,system_virtual_schema', 'gc-grace-periods': '3600,86400,864000,7776000', 'batching': True}}, 'checks': {'compactions-threshold': 250, 'cpu-busy-threshold': 98.0, 'cpu-threshold': 0.0, 'cassandra-data-path': '/c3/cassandra', 'root-disk-threshold': 50, 'cassandra-disk-threshold': 50, 'snapshot-size-cmd': "ls /c3/cassandra/data/data/*/*/snapshots | grep snapshots | sed 's/:$//g' | xargs -I {} du -sk {} | awk '{print $1}' | awk '{s+=$1} END {print s}'", 'snapshot-size-threshold': '40G', 'table-sizes-cmd': "ls -Al /c3/cassandra/data/data/ | awk '{print $9}' | sed 's/\\^r//g' | xargs -I {} du -sk /c3/cassandra/data/data/{}"}, 'get-host-id': {'workers': 32}, 'idps': {'ad': {'email-pattern': '.*@c3.ai', 'uri': 'https://login.microsoftonline.com/53ad779a-93e7-485c-ba20-ac8290d7252b/oauth2/v2.0/authorize?response_type=id_token&response_mode=form_post&client_id=00ff94a8-6b0a-4715-98e0-95490012d818&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fplat.c3ci.cloud%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://login.microsoftonline.com/common/discovery/keys', 'contact': 'Please contact ted.tran@c3.ai.', 'whitelist-file': '/kaqing/members'}, 'okta': {'default': True, 'email-pattern': '.*@c3iot.com', 'uri': 'https://c3energy.okta.com/oauth2/v1/authorize?response_type=id_token&response_mode=form_post&client_id={client_id}&scope=openid+email+profile+groups&redirect_uri=https%3A%2F%2F{host}%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://c3energy.okta.com/oauth2/v1/keys'}}, 'issues': {'workers': 32}, 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'medusa': {'restore-auto-complete': False}, 'nodetool': {'workers': 32, 'samples': 3, 'commands_in_line': 40}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu,mem', 'header': 'POD_NAME,CPU,MEM/LIMIT'}, 'reaper': {'service-name': 'reaper-service', 'port-forward': {'timeout': 86400, 'local-port': 9001}, 'abort-runs-batch': 10, 'show-runs-batch': 100, 'pod': {'cluster-regex': '(.*?-.*?-.*?-.*?)-.*', 'label-selector': 'k8ssandra.io/reaper={cluster}-reaper'}, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-reaper-ui', 'password-item': 'password'}}, 'repair': {'log-path': '/home/cassrepair/logs/', 'image': 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.14', 'secret': 'ciregistryc3iotio', 'env': {'interval': 24, 'timeout': 60, 'pr': False, 'runs': 1}}, 'repl': {'start-drive': 'a', 'auto-enter-app': 'c3/c3', 'auto-enter-only-cluster': True}, 'status': {'columns': 'status,address,load,tokens,owns,host_id,gossip,compactions', 'header': '--,Address,Load,Tokens,Owns,Host ID,GOSSIP,COMPACTIONS'}, 'storage': {'columns': 'pod,volume_root,volume_cassandra,snapshots,data,compactions', 'header': 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS'}, 'watch': {'auto': 'rollout', 'timeout': 3600, 'interval': 10}, 'debug': {'timings': False, 'exit-on-error': False, 'show-parallelism': False, 'show-out': False}}
|
kaqing-2.0.28/adam/version.py
DELETED
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
|
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
|
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
|
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
|