diff --git a/sources/scripts/add_shardkey.py b/sources/scripts/add_shardkey.py index b1c7283..8d501fc 100644 --- a/sources/scripts/add_shardkey.py +++ b/sources/scripts/add_shardkey.py @@ -8,7 +8,6 @@ redisUser = os.environ.get('REDIS_SERVER_USER') redisPassword = os.environ.get('REDIS_SERVER_PWD') redisDBNum = os.environ.get('REDIS_SERVER_DB_KEYS_NUM') -redisDBNumDSVersion = os.environ.get('REDIS_SERVER_DB_DS_VERSION') redisConnectTimeout = 15 if os.environ.get('REDIS_CLUSTER_NODES'): redisClusterNodes = list(os.environ.get('REDIS_CLUSTER_NODES').split(" ")) @@ -20,9 +19,7 @@ shardKey = os.environ.get('DEFAULT_SHARD_KEY') epIP = os.environ.get('SHARD_IP') epPort = os.environ.get('SHARD_PORT') -dsVersion = os.environ.get('APP_VERSION') + '-' + os.environ.get('DS_VERSION_HASH') ipShard = epIP + ':' + epPort -shardDSVersion = ipShard + '-' + dsVersion total_result = {} @@ -53,10 +50,10 @@ def get_redis_status(): ) rc.ping() except Exception as msg_redis: - logger_test_ds.error(f'Failed to check the availability of the Redis Standalone... {msg_redis}\n') + logger_endpoints_ds.error(f'Failed to check the availability of the Redis Standalone... {msg_redis}\n') total_result['CheckRedis'] = 'Failed' else: - logger_test_ds.info('Successful connection to Redis Standalone') + logger_endpoints_ds.info('Successful connection to Redis Standalone') return rc.ping() @@ -75,10 +72,10 @@ def get_redis_cluster_status(): ) rc.ping() except Exception as msg_redis: - logger_test_ds.error(f'Failed to check the availability of the Redis Cluster... {msg_redis}\n') + logger_endpoints_ds.error(f'Failed to check the availability of the Redis Cluster... {msg_redis}\n') total_result['CheckRedis'] = 'Failed' else: - logger_test_ds.info('Successful connection to Redis Cluster') + logger_endpoints_ds.info('Successful connection to Redis Cluster') return rc.ping() @@ -100,10 +97,10 @@ def get_redis_sentinel_status(): ) rc.ping() except Exception as msg_redis: - logger_test_ds.error(f'Failed to check the availability of the Redis Sentinel... {msg_redis}\n') + logger_endpoints_ds.error(f'Failed to check the availability of the Redis Sentinel... {msg_redis}\n') total_result['CheckRedis'] = 'Failed' else: - logger_test_ds.info('Successful connection to Redis Sentinel') + logger_endpoints_ds.info('Successful connection to Redis Sentinel') return rc.ping() @@ -112,18 +109,16 @@ def add_redis_key(): rc.set(shardKey, ipShard) rc.append(ipShard, f' {shardKey}') test_key = rc.get(shardKey).decode('utf-8') - rc.select(redisDBNumDSVersion) - rc.set(shardDSVersion, '0') except Exception as msg_check_redis: - logger_test_ds.error(f'Error when trying to write a ShardKey to Redis... {msg_check_redis}\n') + logger_endpoints_ds.error(f'Error when trying to write a ShardKey to Redis... {msg_check_redis}\n') total_result['CheckRedis'] = 'Failed' else: - logger_test_ds.info(f'ShardKey {shardKey} = {test_key} was successfully recorded to Redis\n') + logger_endpoints_ds.info(f'ShardKey {shardKey} = {test_key} was successfully recorded to Redis\n') rc.close() def init_redis(): - logger_test_ds.info('Checking Redis availability...') + logger_endpoints_ds.info('Checking Redis availability...') if redisConnectorName == 'redis' and not os.environ.get('REDIS_CLUSTER_NODES'): if get_redis_status() is True: add_redis_key() @@ -137,11 +132,11 @@ def init_redis(): def total_status(): if 'Failed' in total_result.values(): - logger_test_ds.error('Recording of "ShardKey" in Redis failed') + logger_endpoints_ds.error('Recording of "ShardKey" in Redis failed') sys.exit(1) -init_logger('test') -logger_test_ds = logging.getLogger('test.ds') +init_logger('endpoints') +logger_endpoints_ds = logging.getLogger('endpoints.ds') init_redis() total_status() diff --git a/sources/scripts/add_shardkey_dsversion.py b/sources/scripts/add_shardkey_dsversion.py new file mode 100644 index 0000000..a7becd0 --- /dev/null +++ b/sources/scripts/add_shardkey_dsversion.py @@ -0,0 +1,154 @@ +import os +import sys +import logging +import time +import subprocess + +redisConnectorName = os.environ.get('REDIS_CONNECTOR_NAME') +redisHost = os.environ.get('REDIS_SERVER_HOST') +redisPort = os.environ.get('REDIS_SERVER_PORT') +redisUser = os.environ.get('REDIS_SERVER_USER') +redisPassword = os.environ.get('REDIS_SERVER_PWD') +redisDBNumDSVersion = os.environ.get('REDIS_SERVER_DB_DS_VERSION') +redisConnectTimeout = 15 +if os.environ.get('REDIS_CLUSTER_NODES'): + redisClusterNodes = list(os.environ.get('REDIS_CLUSTER_NODES').split(" ")) + redisClusterNode = redisClusterNodes[0].split(":")[0] + redisClusterPort = redisClusterNodes[0].split(":")[1] +if redisConnectorName == 'ioredis': + redisSentinelGroupName = os.environ.get('REDIS_SENTINEL_GROUP_NAME') + +shardKey = os.environ.get('DEFAULT_SHARD_KEY') +epIP = os.environ.get('SHARD_IP') +epPort = os.environ.get('SHARD_PORT') +dsVersion = os.environ.get('APP_VERSION') + '-' + os.environ.get('DS_VERSION_HASH') +ipShard = epIP + ':' + epPort +shardDSVersion = ipShard + '-' + dsVersion + + +def init_logger(name): + logger = logging.getLogger(name) + formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' + logger.setLevel(logging.DEBUG) + stdout = logging.StreamHandler() + stdout.setFormatter(logging.Formatter(formatter)) + stdout.setLevel(logging.DEBUG) + logger.addHandler(stdout) + logger.info('Running the Redis initialization script with the "shardKey" value for the replica\n') + + +def get_redis_status(): + import redis + global rc + try: + rc = redis.Redis( + host=redisHost, + port=redisPort, + db=redisDBNumDSVersion, + password=redisPassword, + username=redisUser, + socket_connect_timeout=redisConnectTimeout, + retry_on_timeout=True + ) + rc.ping() + except Exception as msg_redis: + logger_endpoints_ds.error('Failed to check the availability of the Redis Standalone... {}\n'.format(msg_redis)) + else: + logger_endpoints_ds.info('Successful connection to Redis Standalone') + return rc.ping() + + +def get_redis_cluster_status(): + from redis.cluster import RedisCluster as Redis + from redis.cluster import ClusterNode + global rc + try: + nodes = [ClusterNode(redisClusterNode, redisClusterPort)] + rc = Redis( + startup_nodes=nodes, + username=redisUser, + password=redisPassword, + socket_connect_timeout=redisConnectTimeout, + retry_on_timeout=True + ) + rc.ping() + except Exception as msg_redis: + logger_endpoints_ds.error('Failed to check the availability of the Redis Cluster... {}\n'.format(msg_redis)) + else: + logger_endpoints_ds.info('Successful connection to Redis Cluster') + return rc.ping() + + +def get_redis_sentinel_status(): + import redis + from redis import Sentinel + global rc + try: + sentinel = Sentinel([(redisHost, redisPort)], socket_timeout=redisConnectTimeout) + master_host, master_port = sentinel.discover_master(redisSentinelGroupName) + rc = redis.Redis( + host=master_host, + port=master_port, + db=redisDBNumDSVersion, + password=redisPassword, + username=redisUser, + socket_connect_timeout=redisConnectTimeout, + retry_on_timeout=True + ) + rc.ping() + except Exception as msg_redis: + logger_endpoints_ds.error('Failed to check the availability of the Redis Sentinel... {}\n'.format(msg_redis)) + else: + logger_endpoints_ds.info('Successful connection to Redis Sentinel') + return rc.ping() + + +def add_redis_key(): + if not rc.exists(shardDSVersion): + try: + rc.set(shardDSVersion, '0') + except Exception as msg_check_redis: + logger_endpoints_ds.error('Error when trying to write ShardKey with DS version to Redis... {}\n'.format(msg_check_redis)) + else: + rc.close() + else: + rc.close() + + +def init_redis(): + logger_endpoints_ds.info('Checking Redis availability...') + if redisConnectorName == 'redis' and not os.environ.get('REDIS_CLUSTER_NODES'): + if get_redis_status() is True: + add_redis_key() + elif redisConnectorName == 'redis' and os.environ.get('REDIS_CLUSTER_NODES'): + if get_redis_cluster_status() is True: + add_redis_key() + elif redisConnectorName == 'ioredis': + if get_redis_sentinel_status() is True: + add_redis_key() + + +def check_ds(): + while True: + if not os.path.exists('/scripts/checkds.txt'): + try: + ds_status = ["/bin/bash", "-c", "curl -I -s http://localhost:8888/index.html | awk '/^HTTP/{print $2}'"] + ds_status_process = subprocess.Popen(ds_status, stdout=subprocess.PIPE) + ds_status_result = int(ds_status_process.communicate()[0]) + if ds_status_result == 200: + init_redis() + build_status = open('/scripts/checkds.txt', 'w') + build_status.write('Completed') + build_status.close() + else: + time.sleep(1) + except Exception as msg_ds_status: + logger_endpoints_ds.error('Error when trying to get DS status... {}'. format(msg_ds_status)) + time.sleep(1) + else: + time.sleep(5) + + +init_logger('endpoints') +logger_endpoints_ds = logging.getLogger('endpoints.ds') +check_ds() diff --git a/sources/scripts/remove_shardkey.py b/sources/scripts/remove_shardkey.py index 1d5c320..52656b9 100644 --- a/sources/scripts/remove_shardkey.py +++ b/sources/scripts/remove_shardkey.py @@ -58,10 +58,10 @@ def get_redis_status(redis_db): ) rc.ping() except Exception as msg_redis: - logger_test_ds.error('Failed to check the availability of the Redis Standalone... {}\n'.format(msg_redis)) + logger_endpoints_ds.error('Failed to check the availability of the Redis Standalone... {}\n'.format(msg_redis)) total_result['CheckRedis'] = 'Failed' else: - logger_test_ds.info('Successful connection to Redis Standalone') + logger_endpoints_ds.info('Successful connection to Redis Standalone') return rc.ping() @@ -80,10 +80,10 @@ def get_redis_cluster_status(): ) rc.ping() except Exception as msg_redis: - logger_test_ds.error('Failed to check the availability of the Redis Cluster... {}\n'.format(msg_redis)) + logger_endpoints_ds.error('Failed to check the availability of the Redis Cluster... {}\n'.format(msg_redis)) total_result['CheckRedis'] = 'Failed' else: - logger_test_ds.info('Successful connection to Redis Cluster') + logger_endpoints_ds.info('Successful connection to Redis Cluster') return rc.ping() @@ -105,10 +105,10 @@ def get_redis_sentinel_status(redis_db): ) rc.ping() except Exception as msg_redis: - logger_test_ds.error('Failed to check the availability of the Redis Sentinel... {}\n'.format(msg_redis)) + logger_endpoints_ds.error('Failed to check the availability of the Redis Sentinel... {}\n'.format(msg_redis)) total_result['CheckRedis'] = 'Failed' else: - logger_test_ds.info('Successful connection to Redis Sentinel') + logger_endpoints_ds.info('Successful connection to Redis Sentinel') return rc.ping() @@ -127,17 +127,17 @@ def clear_shard_key(): rc.delete(shardDSVersion) rc.close() except Exception as msg_check_redis: - logger_test_ds.error('Error when trying to delete keys belonging to the {sk} shard from Redis... {em}\n'.format(sk=shardKey, em=msg_check_redis)) + logger_endpoints_ds.error('Error when trying to delete keys belonging to the {sk} shard from Redis... {em}\n'.format(sk=shardKey, em=msg_check_redis)) total_result['CheckRedis'] = 'Failed' else: - logger_test_ds.info('Keys belonging to {} have been successfully deleted from Redis\n'.format(shardKey)) + logger_endpoints_ds.info('Keys belonging to {} have been successfully deleted from Redis\n'.format(shardKey)) else: - logger_test_ds.info('Endpoint shard {} was not found in Redis\n'.format(shardKey)) + logger_endpoints_ds.info('Endpoint shard {} was not found in Redis\n'.format(shardKey)) rc.close() def clear_redis(): - logger_test_ds.info('Checking Redis availability...') + logger_endpoints_ds.info('Checking Redis availability...') if redisConnectorName == 'redis' and not os.environ.get('REDIS_CLUSTER_NODES'): if get_redis_status(redisDBNum) is True: clear_shard_key() @@ -160,7 +160,7 @@ def get_connect_count(): else: return False except Exception as msg_get_connect_count: - logger_test_ds.error('Failed when trying to get the number of connections... {}\n'.format(msg_get_connect_count)) + logger_endpoints_ds.error('Failed when trying to get the number of connections... {}\n'.format(msg_get_connect_count)) total_result['GetConnectCount'] = 'Failed' return False @@ -171,7 +171,7 @@ def shutdown_shard(): process = subprocess.Popen(shutdown_cmd, stdout=subprocess.PIPE) shutdown_result = process.communicate()[0].decode('utf-8') except Exception as msg_url: - logger_test_ds.error('Failed to check the availability of the DocumentServer... {}\n'.format(msg_url)) + logger_endpoints_ds.error('Failed to check the availability of the DocumentServer... {}\n'.format(msg_url)) total_result['ShutdownDS'] = 'Failed' else: if shutdown_result == "true": @@ -180,7 +180,7 @@ def shutdown_shard(): build_status.write('Completed') build_status.close() else: - logger_test_ds.error('The {} shard could not be disabled'.format(shardKey)) + logger_endpoints_ds.error('The {} shard could not be disabled'.format(shardKey)) sys.exit(1) @@ -202,11 +202,11 @@ def prepare_for_shutdown_shard(): def total_status(): if 'Failed' in total_result.values(): - logger_test_ds.error('Could not clear Redis of keys belonging to {}'.format(shardKey)) + logger_endpoints_ds.error('Could not clear Redis of keys belonging to {}'.format(shardKey)) sys.exit(1) -init_logger('test') -logger_test_ds = logging.getLogger('test.ds') +init_logger('endpoints') +logger_endpoints_ds = logging.getLogger('endpoints.ds') prepare_for_shutdown_shard() total_status() diff --git a/templates/configmaps/add-shardkey-dsversion.yaml b/templates/configmaps/add-shardkey-dsversion.yaml new file mode 100644 index 0000000..f6de477 --- /dev/null +++ b/templates/configmaps/add-shardkey-dsversion.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: add-shardkey-dsversion + namespace: {{ include "ds.namespace" . | quote }} + {{- if .Values.commonLabels }} + labels: + {{- include "ds.labels.commonLabels" . | trim | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "ds.annotations.commonAnnotations" ( dict "keyName" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: +{{ (.Files.Glob "sources/scripts/add_shardkey_dsversion.py").AsConfig | indent 2 }} diff --git a/templates/deployments/documentserver.yaml b/templates/deployments/documentserver.yaml index b579cd4..d9a87b2 100644 --- a/templates/deployments/documentserver.yaml +++ b/templates/deployments/documentserver.yaml @@ -99,8 +99,6 @@ spec: env: - name: REDIS_SERVER_DB_KEYS_NUM value: {{ .Values.documentserver.keysRedisDBNum | quote }} - - name: REDIS_SERVER_DB_DS_VERSION - value: {{ .Values.documentserver.dsVersionHashRedisDBNum | quote }} - name: REDIS_SERVER_PWD valueFrom: secretKeyRef: @@ -116,8 +114,6 @@ spec: fieldPath: status.podIP - name: SHARD_PORT value: {{ .Values.documentserver.proxy.containerPorts.http | quote }} - - name: APP_VERSION - value: {{ .Chart.AppVersion | quote }} envFrom: - configMapRef: name: documentserver @@ -152,7 +148,6 @@ spec: livenessProbe: {{- omit .Values.documentserver.proxy.livenessProbe "enabled" | toYaml | nindent 12 }} {{- end }} resources: {{ toYaml .Values.documentserver.proxy.resources | nindent 12 }} - {{- if or .Values.documentserver.proxy.infoAllowedIP .Values.documentserver.proxy.infoAllowedUser }} env: - name: DEFAULT_SHARD_KEY valueFrom: @@ -171,7 +166,6 @@ spec: name: {{ template "ds.info.secretName" . }} key: {{ .Values.documentserver.proxy.infoAllowedSecretKeyName }} {{- end }} - {{- end }} envFrom: - configMapRef: name: documentserver @@ -392,6 +386,42 @@ spec: subPath: pre_stop.sh - name: pre-stop-status mountPath: /scripts/results + + - name: add-shardkey-dsversion + image: {{ .Values.documentserver.initContainers.image.repository }}:{{ .Values.documentserver.initContainers.image.tag }} + imagePullPolicy: {{ .Values.documentserver.initContainers.image.pullPolicy }} + {{- if .Values.documentserver.initContainers.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.documentserver.initContainers.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + resources: {{- toYaml .Values.documentserver.initContainers.resources | nindent 12 }} + env: + - name: REDIS_SERVER_DB_DS_VERSION + value: {{ .Values.documentserver.dsVersionHashRedisDBNum | quote }} + - name: REDIS_SERVER_PWD + valueFrom: + secretKeyRef: + name: {{ template "ds.redis.secretName" . }} + key: {{ .Values.connections.redisSecretKeyName }} + - name: DEFAULT_SHARD_KEY + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: SHARD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: SHARD_PORT + value: {{ .Values.documentserver.proxy.containerPorts.http | quote }} + - name: APP_VERSION + value: {{ .Chart.AppVersion | quote }} + envFrom: + - configMapRef: + name: documentserver + command: ["dumb-init", "python", "/scripts/add_shardkey_dsversion.py"] + volumeMounts: + - name: add-shardkey-dsversion + mountPath: /scripts/add_shardkey_dsversion.py + subPath: add_shardkey_dsversion.py volumes: - name: ds-files emptyDir: {} @@ -433,6 +463,10 @@ spec: configMap: name: add-shardkey defaultMode: 0755 + - name: add-shardkey-dsversion + configMap: + name: add-shardkey-dsversion + defaultMode: 0755 - name: remove-shardkey configMap: name: remove-shardkey