blob: edb7e98c18140ec9e3bc10a6659cceae81433797 [file] [log] [blame]
# Copyright (C) 2020 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
import sys
from cassandra.auth import PlainTextAuthProvider
from fakeredis import FakeStrictRedis
from redis import StrictRedis
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from resultsdbpy.model.cassandra_context import CassandraContext
from resultsdbpy.model.casserole import CasseroleNodes, CasseroleRedis
from resultsdbpy.model.ci_context import BuildbotURLFactory, BuildbotEightURLFactory
from resultsdbpy.model.mock_cassandra_context import MockCassandraContext
from resultsdbpy.model.model import Model
from resultsdbpy.model.repository import WebKitRepository
from resultsdbpy.model.partitioned_redis import PartitionedRedis
MOCK_CASSANDRA = 'mock'
KEYSPACE = 'results_database_example'
class Environment(object):
REDIS_PORT = 6379
def __init__(self, cqleng_allow_schema_management=False):
self.port = int(os.environ.get('PORT', 5000))
# The base environment provides defaults for database information, although that can be explicitly overridden
self.cassandra_server = os.environ.get('CASSANDRA_SERVER', 'localhost')
self.keyspace = os.environ.get('KEYSPACE', KEYSPACE)
self.redis_host = os.environ.get('REDIS_HOST', 'localhost')
self.redis_port = os.environ.get('REDIS_PORT', self.REDIS_PORT)
self.drop_keyspace = cqleng_allow_schema_management and bool(int(os.environ.get('DROP_KEYSPACE', 0)))
self.create_keyspace = cqleng_allow_schema_management and bool(int(os.environ.get('CREATE_KEYSPACE', 1)))
self.cqleng_allow_schema_management = cqleng_allow_schema_management
os.environ['CQLENG_ALLOW_SCHEMA_MANAGEMENT'] = '1' if self.cqleng_allow_schema_management else '0'
for key, value in self.__dict__.items():
if value is None:
raise EnvironmentError(f'{key.upper()} is not defined in the environment')
self.redis_url = os.environ.get('REDIS_URL', None)
self.redis_password = os.environ.get('REDIS_PASSWORD', None)
self.cassandra_username = None
self.cassandra_password = None
if not self.cqleng_allow_schema_management:
self.cassandra_username = os.environ.get('CASSANDRA_USER')
self.cassandra_password = os.environ.get('CASSANDRA_USER_PASSWORD')
if not self.cassandra_username or not self.cassandra_password:
self.cassandra_username = os.environ.get('CASSANDRA_ADMIN')
self.cassandra_password = os.environ.get('CASSANDRA_ADMIN_PASSWORD')
@staticmethod
def obfuscate_password(password):
if password:
return '*' * len(password)
return '-'
def __str__(self):
result = ''
order = [
'port',
'cassandra_server', 'cqleng_allow_schema_management',
'keyspace', 'drop_keyspace', 'create_keyspace',
'cassandra_username', 'cassandra_password',
'redis_url',
'redis_host', 'redis_port', 'redis_password',
]
for key in self.__dict__.keys():
if key not in order:
order.append(key)
for key in order:
value = self.__dict__.get(key)
if value and ('password' in key or 'token' in key or key.endswith('key')):
value = self.obfuscate_password(value)
result += f" {key.upper()}: {value}\n"
return result[:-1]
class ModelFromEnvironment(Model):
TTL_SECONDS = Model.TTL_YEAR * 5
def __init__(self, environment):
nodes = ['localhost']
cassandra_class = CassandraContext
if environment.cassandra_server == MOCK_CASSANDRA:
cassandra_class = MockCassandraContext
auth_provider = None
if environment.cassandra_username and environment.cassandra_password:
auth_provider = PlainTextAuthProvider(environment.cassandra_username, environment.cassandra_password)
if environment.drop_keyspace:
cassandra_class.drop_keyspace(nodes=nodes, keyspace=environment.keyspace, auth_provider=auth_provider)
cassandra = cassandra_class(
nodes=nodes,
keyspace=environment.keyspace,
auth_provider=auth_provider,
create_keyspace=environment.create_keyspace,
replication_map=None,
)
if environment.redis_host == 'mock':
redis = FakeStrictRedis()
elif environment.redis_url:
redis = StrictRedis.from_url(environment.redis_url)
else:
redis = StrictRedis(
port=environment.redis_port,
host=environment.redis_host,
password=environment.redis_password,
)
redis.ping() # Force a connection with the redis database
webkit = WebKitRepository()
super(ModelFromEnvironment, self).__init__(
redis=redis, cassandra=cassandra,
repositories=[webkit],
default_ttl_seconds=self.TTL_SECONDS,
async_processing=True,
)
def main():
environment = Environment(cqleng_allow_schema_management=True)
print(f'Environment for setup:\n{environment}')
ModelFromEnvironment(environment)
if __name__ == '__main__':
main()