def open(self): self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port) log.info(" tmp_dir = %s", self.tmp_dir) # Generate configs template = self.test_resource("zookeeper.properties") properties = os.path.join(self.tmp_dir, "zookeeper.properties") self.render_template(template, properties, vars(self)) # Configure Zookeeper child process args = self.kafka_run_class_args( "org.apache.zookeeper.server.quorum.QuorumPeerMain", properties) env = self.kafka_run_class_env() # Party! self.out("Starting...") timeout = 5 max_timeout = 30 backoff = 1 while True: self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max_timeout) if self.child.wait_for(r"binding to port", timeout=timeout): break self.child.stop() timeout *= 2 time.sleep(backoff) self.out("Done!")
def open(self): if self.running: self.out("Instance already running") return self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") logging.info(" host = %s", self.host) logging.info(" port = %s", self.port) logging.info(" broker_id = %s", self.broker_id) logging.info(" zk_host = %s", self.zk_host) logging.info(" zk_port = %s", self.zk_port) logging.info(" zk_chroot = %s", self.zk_chroot) logging.info(" replicas = %s", self.replicas) logging.info(" partitions = %s", self.partitions) logging.info(" tmp_dir = %s", self.tmp_dir) # Create directories os.mkdir(os.path.join(self.tmp_dir, "logs")) os.mkdir(os.path.join(self.tmp_dir, "data")) # Generate configs template = self.test_resource("kafka.properties") properties = os.path.join(self.tmp_dir, "kafka.properties") self.render_template(template, properties, vars(self)) # Configure Kafka child process args = self.kafka_run_class_args("kafka.Kafka", properties) env = self.kafka_run_class_env() self.child = SpawnedService(args, env) # Party! self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args( "org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zk_host, self.zk_port), "create", "/%s" % self.zk_chroot, "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if proc.wait() != 0: self.out("Failed to create Zookeeper chroot node") self.out(proc.stdout.read()) self.out(proc.stderr.read()) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Done!") self.out("Starting...") self.child.start() self.child.wait_for(r"\[Kafka Server %d\], Started" % self.broker_id) self.out("Done!") self.running = True
def start(self): # Configure Kafka child process properties = self.tmp_dir.join("kafka.properties") jaas_conf = self.tmp_dir.join("kafka_server_jaas.conf") properties_template = self.test_resource("kafka.properties") jaas_conf_template = self.test_resource("kafka_server_jaas.conf") args = self.kafka_run_class_args("kafka.Kafka", properties.strpath) env = self.kafka_run_class_env() if self.sasl_enabled: opts = env.get('KAFKA_OPTS', '').strip() opts += ' -Djava.security.auth.login.config={}'.format( jaas_conf.strpath) env['KAFKA_OPTS'] = opts self.render_template(jaas_conf_template, jaas_conf, vars(self)) timeout = 5 max_timeout = 120 backoff = 1 end_at = time.time() + max_timeout tries = 1 auto_port = (self.port is None) while time.time() < end_at: # We have had problems with port conflicts on travis # so we will try a different port on each retry # unless the fixture was passed a specific port if auto_port: self.port = get_open_port() self.out('Attempting to start on port %d (try #%d)' % (self.port, tries)) self.render_template(properties_template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self._broker_ready(timeout) and self._scram_user_present( timeout): break self.child.dump_logs() self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 backoff += 1 else: raise RuntimeError( 'Failed to start KafkaInstance before max_timeout') (self._client, ) = self.get_clients(1, client_id='_internal_client') self.out("Done!") self.running = True
def open(self): self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port) log.info(" tmp_dir = %s", self.tmp_dir) # Generate configs template = self.test_resource("zookeeper.properties") properties = os.path.join(self.tmp_dir, "zookeeper.properties") self.render_template(template, properties, vars(self)) # Configure Zookeeper child process args = self.kafka_run_class_args("org.apache.zookeeper.server.quorum.QuorumPeerMain", properties) env = self.kafka_run_class_env() # Party! self.out("Starting...") timeout = 5 max_timeout = 30 backoff = 1 while True: self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max_timeout) if self.child.wait_for(r"binding to port", timeout=timeout): break self.child.stop() timeout *= 2 time.sleep(backoff) self.out("Done!")
def open(self): if self.tmp_dir is None: self.tmp_dir = py.path.local.mkdtemp() #pylint: disable=no-member self.tmp_dir.ensure(dir=True) self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port or '(auto)') log.info(" tmp_dir = %s", self.tmp_dir.strpath) # Configure Zookeeper child process template = self.test_resource("zookeeper.properties") properties = self.tmp_dir.join("zookeeper.properties") args = self.kafka_run_class_args( "org.apache.zookeeper.server.quorum.QuorumPeerMain", properties.strpath) env = self.kafka_run_class_env() # Party! timeout = 5 max_timeout = 120 backoff = 1 end_at = time.time() + max_timeout tries = 1 auto_port = (self.port is None) while time.time() < end_at: if auto_port: self.port = get_open_port() self.out('Attempting to start on port %d (try #%d)' % (self.port, tries)) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"binding to port", timeout=timeout): break self.child.dump_logs() self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 backoff += 1 else: raise RuntimeError('Failed to start Zookeeper before max_timeout') self.out("Done!") atexit.register(self.close)
def open(self): if self.running: self.out("Instance already running") return self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port) log.info(" broker_id = %s", self.broker_id) log.info(" zk_host = %s", self.zk_host) log.info(" zk_port = %s", self.zk_port) log.info(" zk_chroot = %s", self.zk_chroot) log.info(" replicas = %s", self.replicas) log.info(" partitions = %s", self.partitions) log.info(" tmp_dir = %s", self.tmp_dir) # Create directories os.mkdir(os.path.join(self.tmp_dir, "logs")) os.mkdir(os.path.join(self.tmp_dir, "data")) # Generate configs template = self.test_resource("kafka.properties") properties = os.path.join(self.tmp_dir, "kafka.properties") self.render_template(template, properties, vars(self)) # Party! self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args("org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zk_host, self.zk_port), "create", "/%s" % self.zk_chroot, "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if proc.wait() != 0: self.out("Failed to create Zookeeper chroot node") self.out(proc.stdout.read()) self.out(proc.stderr.read()) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Done!") self.out("Starting...") # Configure Kafka child process args = self.kafka_run_class_args("kafka.Kafka", properties) env = self.kafka_run_class_env() while True: self.child = SpawnedService(args, env) self.child.start() if self.child.wait_for(r"\[Kafka Server %d\], Started" % self.broker_id, timeout=5): break self.child.stop() self.out("Done!") self.running = True
def open(self): self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port) log.info(" tmp_dir = %s", self.tmp_dir) # Generate configs template = self.test_resource("zookeeper.properties") properties = os.path.join(self.tmp_dir, "zookeeper.properties") self.render_template(template, properties, vars(self)) # Configure Zookeeper child process args = self.kafka_run_class_args( "org.apache.zookeeper.server.quorum.QuorumPeerMain", properties) env = self.kafka_run_class_env() # Party! timeout = 5 max_timeout = 30 backoff = 1 end_at = time.time() + max_timeout tries = 1 while time.time() < end_at: self.out('Attempting to start (try #%d)' % tries) try: os.stat(properties) except: log.warning('Config %s not found -- re-rendering', properties) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"binding to port", timeout=timeout): break self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 else: raise Exception('Failed to start Zookeeper before max_timeout') self.out("Done!") atexit.register(self.close)
def start(self): # Configure Kafka child process properties = self.tmp_dir.join("kafka.properties") template = self.test_resource("kafka.properties") args = self.kafka_run_class_args("kafka.Kafka", properties.strpath) env = self.kafka_run_class_env() timeout = 5 max_timeout = 120 backoff = 1 end_at = time.time() + max_timeout tries = 1 auto_port = (self.port is None) while time.time() < end_at: # We have had problems with port conflicts on travis # so we will try a different port on each retry # unless the fixture was passed a specific port if auto_port: self.port = get_open_port() self.out('Attempting to start on port %d (try #%d)' % (self.port, tries)) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(self.start_pattern, timeout=timeout): break self.child.dump_logs() self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 backoff += 1 else: raise RuntimeError( 'Failed to start KafkaInstance before max_timeout') (self._client, ) = self.get_clients(1, '_internal_client') self.out("Done!") self.running = True
class ZookeeperFixture(Fixture): @classmethod def instance(cls): if "ZOOKEEPER_URI" in os.environ: parse = urlparse(os.environ["ZOOKEEPER_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: (host, port) = ("127.0.0.1", get_open_port()) fixture = cls(host, port) fixture.open() return fixture def __init__(self, host, port): self.host = host self.port = port self.tmp_dir = None self.child = None def out(self, message): log.info("*** Zookeeper [%s:%d]: %s", self.host, self.port, message) def open(self): self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port) log.info(" tmp_dir = %s", self.tmp_dir) # Generate configs template = self.test_resource("zookeeper.properties") properties = os.path.join(self.tmp_dir, "zookeeper.properties") self.render_template(template, properties, vars(self)) # Configure Zookeeper child process args = self.kafka_run_class_args("org.apache.zookeeper.server.quorum.QuorumPeerMain", properties) env = self.kafka_run_class_env() # Party! self.out("Starting...") while True: self.child = SpawnedService(args, env) self.child.start() if self.child.wait_for(r"binding to port", timeout=5): break self.child.stop() self.out("Done!") def close(self): self.out("Stopping...") self.child.stop() self.child = None self.out("Done!") shutil.rmtree(self.tmp_dir)
def open(self): self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") logging.info(" host = %s", self.host) logging.info(" port = %s", self.port) logging.info(" tmp_dir = %s", self.tmp_dir) # Generate configs template = self.test_resource("zookeeper.properties") properties = os.path.join(self.tmp_dir, "zookeeper.properties") self.render_template(template, properties, vars(self)) # Configure Zookeeper child process self.child = SpawnedService( self.kafka_run_class_args( "org.apache.zookeeper.server.quorum.QuorumPeerMain", properties)) # Party! self.out("Starting...") self.child.start() self.child.wait_for(r"Snapshotting") self.out("Done!")
class ZookeeperFixture(Fixture): @classmethod def instance(cls): if "ZOOKEEPER_URI" in os.environ: parse = urlparse(os.environ["ZOOKEEPER_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: (host, port) = ("127.0.0.1", get_open_port()) fixture = cls(host, port) fixture.open() return fixture def __init__(self, host, port): self.host = host self.port = port self.tmp_dir = None self.child = None def out(self, message): logging.info("*** Zookeeper [%s:%d]: %s", self.host, self.port, message) def open(self): self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") logging.info(" host = %s", self.host) logging.info(" port = %s", self.port) logging.info(" tmp_dir = %s", self.tmp_dir) # Generate configs template = self.test_resource("zookeeper.properties") properties = os.path.join(self.tmp_dir, "zookeeper.properties") self.render_template(template, properties, vars(self)) # Configure Zookeeper child process self.child = SpawnedService( self.kafka_run_class_args( "org.apache.zookeeper.server.quorum.QuorumPeerMain", properties)) # Party! self.out("Starting...") self.child.start() self.child.wait_for(r"Snapshotting") self.out("Done!") def close(self): self.out("Stopping...") self.child.stop() self.child = None self.out("Done!") shutil.rmtree(self.tmp_dir)
def open(self): if self.tmp_dir is None: self.tmp_dir = py.path.local.mkdtemp() #pylint: disable=no-member self.tmp_dir.ensure(dir=True) self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port or '(auto)') log.info(" tmp_dir = %s", self.tmp_dir.strpath) # Configure Zookeeper child process template = self.test_resource("zookeeper.properties") properties = self.tmp_dir.join("zookeeper.properties") args = self.kafka_run_class_args("org.apache.zookeeper.server.quorum.QuorumPeerMain", properties.strpath) env = self.kafka_run_class_env() # Party! timeout = 5 max_timeout = 120 backoff = 1 end_at = time.time() + max_timeout tries = 1 auto_port = (self.port is None) while time.time() < end_at: if auto_port: self.port = get_open_port() self.out('Attempting to start on port %d (try #%d)' % (self.port, tries)) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"binding to port", timeout=timeout): break self.child.dump_logs() self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 backoff += 1 else: raise RuntimeError('Failed to start Zookeeper before max_timeout') self.out("Done!") atexit.register(self.close)
def open(self): self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port) log.info(" tmp_dir = %s", self.tmp_dir) # Generate configs template = self.test_resource("zookeeper.properties") properties = os.path.join(self.tmp_dir, "zookeeper.properties") self.render_template(template, properties, vars(self)) # Configure Zookeeper child process args = self.kafka_run_class_args("org.apache.zookeeper.server.quorum.QuorumPeerMain", properties) env = self.kafka_run_class_env() # Party! timeout = 5 max_timeout = 30 backoff = 1 end_at = time.time() + max_timeout tries = 1 while time.time() < end_at: self.out('Attempting to start (try #%d)' % tries) try: os.stat(properties) except: log.warning('Config %s not found -- re-rendering', properties) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"binding to port", timeout=timeout): break self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 else: raise Exception('Failed to start Zookeeper before max_timeout') self.out("Done!") atexit.register(self.close)
def start(self): # Configure Kafka child process properties = self.tmp_dir.join("kafka.properties") template = self.test_resource("kafka.properties") args = self.kafka_run_class_args("kafka.Kafka", properties.strpath) env = self.kafka_run_class_env() timeout = 5 max_timeout = 120 backoff = 1 end_at = time.time() + max_timeout tries = 1 auto_port = (self.port is None) while time.time() < end_at: # We have had problems with port conflicts on travis # so we will try a different port on each retry # unless the fixture was passed a specific port if auto_port: self.port = get_open_port() self.out('Attempting to start on port %d (try #%d)' % (self.port, tries)) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(self.start_pattern, timeout=timeout): break self.child.dump_logs() self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 backoff += 1 else: raise RuntimeError('Failed to start KafkaInstance before max_timeout') (self._client,) = self.get_clients(1, '_internal_client') self.out("Done!") self.running = True
def open(self): self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") logging.info(" host = %s", self.host) logging.info(" port = %s", self.port) logging.info(" tmp_dir = %s", self.tmp_dir) # Generate configs template = self.test_resource("zookeeper.properties") properties = os.path.join(self.tmp_dir, "zookeeper.properties") self.render_template(template, properties, vars(self)) # Configure Zookeeper child process args = self.kafka_run_class_args("org.apache.zookeeper.server.quorum.QuorumPeerMain", properties) env = self.kafka_run_class_env() self.child = SpawnedService(args, env) # Party! self.out("Starting...") self.child.start() self.child.wait_for(r"Snapshotting") self.out("Done!")
class KafkaFixture(Fixture): broker_user = '******' broker_password = '******' @classmethod def instance(cls, broker_id, zookeeper, zk_chroot=None, host=None, port=None, transport='PLAINTEXT', replicas=1, partitions=2, sasl_mechanism=None, auto_create_topic=True, tmp_dir=None): if zk_chroot is None: zk_chroot = "kafka-python_" + str(uuid.uuid4()).replace("-", "_") if "KAFKA_URI" in os.environ: parse = urlparse(os.environ["KAFKA_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: if host is None: host = "localhost" fixture = KafkaFixture(host, port, broker_id, zookeeper, zk_chroot, transport=transport, replicas=replicas, partitions=partitions, sasl_mechanism=sasl_mechanism, auto_create_topic=auto_create_topic, tmp_dir=tmp_dir) fixture.open() return fixture def __init__(self, host, port, broker_id, zookeeper, zk_chroot, replicas=1, partitions=2, transport='PLAINTEXT', sasl_mechanism=None, auto_create_topic=True, tmp_dir=None): super(KafkaFixture, self).__init__() self.host = host self.port = port self.broker_id = broker_id self.auto_create_topic = auto_create_topic self.transport = transport.upper() if sasl_mechanism is not None: self.sasl_mechanism = sasl_mechanism.upper() else: self.sasl_mechanism = None self.ssl_dir = self.test_resource('ssl') # TODO: checking for port connection would be better than scanning logs # until then, we need the pattern to work across all supported broker versions # The logging format changed slightly in 1.0.0 self.start_pattern = r"\[Kafka ?Server (id=)?%d\],? started" % ( broker_id, ) # Need to wait until the broker has fetched user configs from zookeeper in case we use scram as sasl mechanism self.scram_pattern = r"Removing Produce quota for user %s" % ( self.broker_user) self.zookeeper = zookeeper self.zk_chroot = zk_chroot # Add the attributes below for the template binding self.zk_host = self.zookeeper.host self.zk_port = self.zookeeper.port self.replicas = replicas self.partitions = partitions self.tmp_dir = tmp_dir self.running = False self._client = None self.sasl_config = '' self.jaas_config = '' def _sasl_config(self): if not self.sasl_enabled: return '' sasl_config = ('sasl.enabled.mechanisms={mechanism}\n' 'sasl.mechanism.inter.broker.protocol={mechanism}\n') return sasl_config.format(mechanism=self.sasl_mechanism) def _jaas_config(self): if not self.sasl_enabled: return '' elif self.sasl_mechanism == 'PLAIN': jaas_config = ( 'org.apache.kafka.common.security.plain.PlainLoginModule required\n' ' username="******" password="******" user_{user}="{password}";\n' ) elif self.sasl_mechanism in ("SCRAM-SHA-256", "SCRAM-SHA-512"): jaas_config = ( 'org.apache.kafka.common.security.scram.ScramLoginModule required\n' ' username="******" password="******";\n') else: raise ValueError( "SASL mechanism {} currently not supported".format( self.sasl_mechanism)) return jaas_config.format(user=self.broker_user, password=self.broker_password) def _add_scram_user(self): self.out("Adding SCRAM credentials for user {} to zookeeper.".format( self.broker_user)) args = self.kafka_run_class_args( "kafka.admin.ConfigCommand", "--zookeeper", "%s:%d/%s" % (self.zookeeper.host, self.zookeeper.port, self.zk_chroot), "--alter", "--entity-type", "users", "--entity-name", self.broker_user, "--add-config", "{}=[password={}]".format(self.sasl_mechanism, self.broker_password), ) env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communicate() if proc.returncode != 0: self.out("Failed to save credentials to zookeeper!") self.out(stdout) self.out(stderr) raise RuntimeError("Failed to save credentials to zookeeper!") self.out("User created.") @property def sasl_enabled(self): return self.sasl_mechanism is not None def bootstrap_server(self): return '%s:%d' % (self.host, self.port) def kafka_run_class_env(self): env = super(KafkaFixture, self).kafka_run_class_env() env['LOG_DIR'] = self.tmp_dir.join('logs').strpath return env def out(self, message): log.info("*** Kafka [%s:%s]: %s", self.host, self.port or '(auto)', message) def _create_zk_chroot(self): self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args( "org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zookeeper.host, self.zookeeper.port), "create", "/%s" % (self.zk_chroot, ), "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communicate() if proc.returncode != 0: self.out("Failed to create Zookeeper chroot node") self.out(stdout) self.out(stderr) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Kafka chroot created in Zookeeper!") def start(self): # Configure Kafka child process properties = self.tmp_dir.join("kafka.properties") jaas_conf = self.tmp_dir.join("kafka_server_jaas.conf") properties_template = self.test_resource("kafka.properties") jaas_conf_template = self.test_resource("kafka_server_jaas.conf") args = self.kafka_run_class_args("kafka.Kafka", properties.strpath) env = self.kafka_run_class_env() if self.sasl_enabled: opts = env.get('KAFKA_OPTS', '').strip() opts += ' -Djava.security.auth.login.config={}'.format( jaas_conf.strpath) env['KAFKA_OPTS'] = opts self.render_template(jaas_conf_template, jaas_conf, vars(self)) timeout = 5 max_timeout = 120 backoff = 1 end_at = time.time() + max_timeout tries = 1 auto_port = (self.port is None) while time.time() < end_at: # We have had problems with port conflicts on travis # so we will try a different port on each retry # unless the fixture was passed a specific port if auto_port: self.port = get_open_port() self.out('Attempting to start on port %d (try #%d)' % (self.port, tries)) self.render_template(properties_template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self._broker_ready(timeout) and self._scram_user_present( timeout): break self.child.dump_logs() self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 backoff += 1 else: raise RuntimeError( 'Failed to start KafkaInstance before max_timeout') (self._client, ) = self.get_clients(1, client_id='_internal_client') self.out("Done!") self.running = True def _broker_ready(self, timeout): return self.child.wait_for(self.start_pattern, timeout=timeout) def _scram_user_present(self, timeout): # no need to wait for scram user if scram is not used if not self.sasl_enabled or not self.sasl_mechanism.startswith( 'SCRAM-SHA-'): return True return self.child.wait_for(self.scram_pattern, timeout=timeout) def open(self): if self.running: self.out("Instance already running") return # Create directories if self.tmp_dir is None: self.tmp_dir = py.path.local.mkdtemp() #pylint: disable=no-member self.tmp_dir.ensure(dir=True) self.tmp_dir.ensure('logs', dir=True) self.tmp_dir.ensure('data', dir=True) self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port or '(auto)') log.info(" transport = %s", self.transport) log.info(" sasl_mechanism = %s", self.sasl_mechanism) log.info(" broker_id = %s", self.broker_id) log.info(" zk_host = %s", self.zookeeper.host) log.info(" zk_port = %s", self.zookeeper.port) log.info(" zk_chroot = %s", self.zk_chroot) log.info(" replicas = %s", self.replicas) log.info(" partitions = %s", self.partitions) log.info(" tmp_dir = %s", self.tmp_dir.strpath) self._create_zk_chroot() self.sasl_config = self._sasl_config() self.jaas_config = self._jaas_config() # add user to zookeeper for the first server if self.sasl_enabled and self.sasl_mechanism.startswith( "SCRAM-SHA") and self.broker_id == 0: self._add_scram_user() self.start() atexit.register(self.close) def __del__(self): self.close() def stop(self): if not self.running: self.out("Instance already stopped") return self.out("Stopping...") self.child.stop() self.child = None self.running = False self.out("Stopped!") def close(self): self.stop() if self.tmp_dir is not None: self.tmp_dir.remove() self.tmp_dir = None self.out("Done!") def dump_logs(self): super(KafkaFixture, self).dump_logs() self.zookeeper.dump_logs() def _send_request(self, request, timeout=None): def _failure(error): raise error retries = 10 while True: node_id = self._client.least_loaded_node() for connect_retry in range(40): self._client.maybe_connect(node_id) if self._client.connected(node_id): break self._client.poll(timeout_ms=100) else: raise RuntimeError( 'Could not connect to broker with node id %d' % (node_id, )) try: future = self._client.send(node_id, request) future.error_on_callbacks = True future.add_errback(_failure) self._client.poll(future=future, timeout_ms=timeout) return future.value except Exception as exc: time.sleep(1) retries -= 1 if retries == 0: raise exc else: pass # retry def _create_topic(self, topic_name, num_partitions=None, replication_factor=None, timeout_ms=10000): if num_partitions is None: num_partitions = self.partitions if replication_factor is None: replication_factor = self.replicas # Try different methods to create a topic, from the fastest to the slowest if self.auto_create_topic and num_partitions == self.partitions and replication_factor == self.replicas: self._create_topic_via_metadata(topic_name, timeout_ms) elif env_kafka_version() >= (0, 10, 1, 0): try: self._create_topic_via_admin_api(topic_name, num_partitions, replication_factor, timeout_ms) except InvalidReplicationFactorError: # wait and try again # on travis the brokers sometimes take a while to find themselves time.sleep(0.5) self._create_topic_via_admin_api(topic_name, num_partitions, replication_factor, timeout_ms) else: self._create_topic_via_cli(topic_name, num_partitions, replication_factor) def _create_topic_via_metadata(self, topic_name, timeout_ms=10000): self._send_request(MetadataRequest[0]([topic_name]), timeout_ms) def _create_topic_via_admin_api(self, topic_name, num_partitions, replication_factor, timeout_ms=10000): request = CreateTopicsRequest[0]( [(topic_name, num_partitions, replication_factor, [], [])], timeout_ms) response = self._send_request(request, timeout=timeout_ms) for topic_result in response.topic_errors: error_code = topic_result[1] if error_code != 0: raise errors.for_code(error_code) def _create_topic_via_cli(self, topic_name, num_partitions, replication_factor): args = self.kafka_run_class_args('kafka.admin.TopicCommand', '--zookeeper', '%s:%s/%s' % (self.zookeeper.host, self.zookeeper.port, self.zk_chroot), '--create', '--topic', topic_name, '--partitions', self.partitions \ if num_partitions is None else num_partitions, '--replication-factor', self.replicas \ if replication_factor is None \ else replication_factor) if env_kafka_version() >= (0, 10): args.append('--if-not-exists') env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communicate() if proc.returncode != 0: if 'kafka.common.TopicExistsException' not in stdout: self.out("Failed to create topic %s" % (topic_name, )) self.out(stdout) self.out(stderr) raise RuntimeError("Failed to create topic %s" % (topic_name, )) def get_topic_names(self): args = self.kafka_run_class_args( 'kafka.admin.TopicCommand', '--zookeeper', '%s:%s/%s' % (self.zookeeper.host, self.zookeeper.port, self.zk_chroot), '--list') env = self.kafka_run_class_env() env.pop('KAFKA_LOG4J_OPTS') proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communicate() if proc.returncode != 0: self.out("Failed to list topics!") self.out(stdout) self.out(stderr) raise RuntimeError("Failed to list topics!") return stdout.decode().splitlines(False) def create_topics(self, topic_names, num_partitions=None, replication_factor=None): for topic_name in topic_names: self._create_topic(topic_name, num_partitions, replication_factor) def _enrich_client_params(self, params, **defaults): params = params.copy() for key, value in defaults.items(): params.setdefault(key, value) params.setdefault('bootstrap_servers', self.bootstrap_server()) if self.sasl_enabled: params.setdefault('sasl_mechanism', self.sasl_mechanism) params.setdefault('security_protocol', self.transport) if self.sasl_mechanism in ('PLAIN', 'SCRAM-SHA-256', 'SCRAM-SHA-512'): params.setdefault('sasl_plain_username', self.broker_user) params.setdefault('sasl_plain_password', self.broker_password) return params @staticmethod def _create_many_clients(cnt, cls, *args, **params): client_id = params['client_id'] for _ in range(cnt): params['client_id'] = '%s_%s' % (client_id, random_string(4)) yield cls(*args, **params) def get_clients(self, cnt=1, **params): params = self._enrich_client_params(params, client_id='client') for client in self._create_many_clients(cnt, KafkaClient, **params): yield client def get_admin_clients(self, cnt, **params): params = self._enrich_client_params(params, client_id='admin_client') for client in self._create_many_clients(cnt, KafkaAdminClient, **params): yield client def get_consumers(self, cnt, topics, **params): params = self._enrich_client_params(params, client_id='consumer', heartbeat_interval_ms=500, auto_offset_reset='earliest') for client in self._create_many_clients(cnt, KafkaConsumer, *topics, **params): yield client def get_producers(self, cnt, **params): params = self._enrich_client_params(params, client_id='producer') for client in self._create_many_clients(cnt, KafkaProducer, **params): yield client
class ZookeeperFixture(Fixture): @classmethod def instance(cls): if "ZOOKEEPER_URI" in os.environ: parse = urlparse(os.environ["ZOOKEEPER_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: (host, port) = ("127.0.0.1", None) fixture = cls(host, port) fixture.open() return fixture def __init__(self, host, port, tmp_dir=None): super(ZookeeperFixture, self).__init__() self.host = host self.port = port self.tmp_dir = tmp_dir def kafka_run_class_env(self): env = super(ZookeeperFixture, self).kafka_run_class_env() env['LOG_DIR'] = self.tmp_dir.join('logs').strpath return env def out(self, message): log.info("*** Zookeeper [%s:%s]: %s", self.host, self.port or '(auto)', message) def open(self): if self.tmp_dir is None: self.tmp_dir = py.path.local.mkdtemp() #pylint: disable=no-member self.tmp_dir.ensure(dir=True) self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port or '(auto)') log.info(" tmp_dir = %s", self.tmp_dir.strpath) # Configure Zookeeper child process template = self.test_resource("zookeeper.properties") properties = self.tmp_dir.join("zookeeper.properties") args = self.kafka_run_class_args( "org.apache.zookeeper.server.quorum.QuorumPeerMain", properties.strpath) env = self.kafka_run_class_env() # Party! timeout = 5 max_timeout = 120 backoff = 1 end_at = time.time() + max_timeout tries = 1 auto_port = (self.port is None) while time.time() < end_at: if auto_port: self.port = get_open_port() self.out('Attempting to start on port %d (try #%d)' % (self.port, tries)) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"binding to port", timeout=timeout): break self.child.dump_logs() self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 backoff += 1 else: raise RuntimeError('Failed to start Zookeeper before max_timeout') self.out("Done!") atexit.register(self.close) def close(self): if self.child is None: return self.out("Stopping...") self.child.stop() self.child = None self.out("Done!") self.tmp_dir.remove() def __del__(self): self.close()
class KafkaFixture(Fixture): @classmethod def instance(cls, broker_id, zk_host, zk_port, zk_chroot=None, replicas=1, partitions=2): if zk_chroot is None: zk_chroot = "kafka-python_" + str(uuid.uuid4()).replace("-", "_") if "KAFKA_URI" in os.environ: parse = urlparse(os.environ["KAFKA_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: (host, port) = ("127.0.0.1", get_open_port()) fixture = KafkaFixture(host, port, broker_id, zk_host, zk_port, zk_chroot, replicas, partitions) fixture.open() return fixture def __init__(self, host, port, broker_id, zk_host, zk_port, zk_chroot, replicas=1, partitions=2): self.host = host self.port = port self.broker_id = broker_id self.zk_host = zk_host self.zk_port = zk_port self.zk_chroot = zk_chroot self.replicas = replicas self.partitions = partitions self.tmp_dir = None self.child = None self.running = False def out(self, message): log.info("*** Kafka [%s:%d]: %s", self.host, self.port, message) def open(self): if self.running: self.out("Instance already running") return self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port) log.info(" broker_id = %s", self.broker_id) log.info(" zk_host = %s", self.zk_host) log.info(" zk_port = %s", self.zk_port) log.info(" zk_chroot = %s", self.zk_chroot) log.info(" replicas = %s", self.replicas) log.info(" partitions = %s", self.partitions) log.info(" tmp_dir = %s", self.tmp_dir) # Create directories os.mkdir(os.path.join(self.tmp_dir, "logs")) os.mkdir(os.path.join(self.tmp_dir, "data")) # Generate configs template = self.test_resource("kafka.properties") properties = os.path.join(self.tmp_dir, "kafka.properties") self.render_template(template, properties, vars(self)) # Party! self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args( "org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zk_host, self.zk_port), "create", "/%s" % self.zk_chroot, "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if proc.wait() != 0: self.out("Failed to create Zookeeper chroot node") self.out(proc.stdout.read()) self.out(proc.stderr.read()) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Done!") self.out("Starting...") # Configure Kafka child process args = self.kafka_run_class_args("kafka.Kafka", properties) env = self.kafka_run_class_env() timeout = 5 max_timeout = 30 backoff = 1 while True: self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max_timeout) if self.child.wait_for(r"\[Kafka Server %d\], Started" % self.broker_id, timeout=timeout): break self.child.stop() timeout *= 2 time.sleep(backoff) self.out("Done!") self.running = True def close(self): if not self.running: self.out("Instance already stopped") return self.out("Stopping...") self.child.stop() self.child = None self.out("Done!") shutil.rmtree(self.tmp_dir) self.running = False
def open(self): if self.running: self.out("Instance already running") return self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port or '(auto)') log.info(" transport = %s", self.transport) log.info(" broker_id = %s", self.broker_id) log.info(" zk_host = %s", self.zk_host) log.info(" zk_port = %s", self.zk_port) log.info(" zk_chroot = %s", self.zk_chroot) log.info(" replicas = %s", self.replicas) log.info(" partitions = %s", self.partitions) log.info(" tmp_dir = %s", self.tmp_dir) # Create directories os.mkdir(os.path.join(self.tmp_dir, "logs")) os.mkdir(os.path.join(self.tmp_dir, "data")) self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args("org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zk_host, self.zk_port), "create", "/%s" % self.zk_chroot, "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if proc.wait() != 0: self.out("Failed to create Zookeeper chroot node") self.out(proc.stdout.read()) self.out(proc.stderr.read()) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Done!") # Configure Kafka child process properties = os.path.join(self.tmp_dir, "kafka.properties") template = self.test_resource("kafka.properties") args = self.kafka_run_class_args("kafka.Kafka", properties) env = self.kafka_run_class_env() timeout = 5 max_timeout = 30 backoff = 1 end_at = time.time() + max_timeout tries = 1 auto_port = (self.port is None) while time.time() < end_at: # We have had problems with port conflicts on travis # so we will try a different port on each retry # unless the fixture was passed a specific port if auto_port: self.port = get_open_port() self.out('Attempting to start on port %d (try #%d)' % (self.port, tries)) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"\[Kafka Server %d\], Started" % self.broker_id, timeout=timeout): break self.child.dump_logs() self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 else: raise Exception('Failed to start KafkaInstance before max_timeout') self.out("Done!") self.running = True atexit.register(self.close)
def open(self): if self.running: self.out("Instance already running") return self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port or '(auto)') log.info(" transport = %s", self.transport) log.info(" broker_id = %s", self.broker_id) log.info(" zk_host = %s", self.zk_host) log.info(" zk_port = %s", self.zk_port) log.info(" zk_chroot = %s", self.zk_chroot) log.info(" replicas = %s", self.replicas) log.info(" partitions = %s", self.partitions) log.info(" tmp_dir = %s", self.tmp_dir) # Create directories os.mkdir(os.path.join(self.tmp_dir, "logs")) os.mkdir(os.path.join(self.tmp_dir, "data")) self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args( "org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zk_host, self.zk_port), "create", "/%s" % self.zk_chroot, "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if proc.wait() != 0: self.out("Failed to create Zookeeper chroot node") self.out(proc.stdout.read()) self.out(proc.stderr.read()) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Done!") # Configure Kafka child process properties = os.path.join(self.tmp_dir, "kafka.properties") template = self.test_resource("kafka.properties") args = self.kafka_run_class_args("kafka.Kafka", properties) env = self.kafka_run_class_env() timeout = 5 max_timeout = 30 backoff = 1 end_at = time.time() + max_timeout tries = 1 auto_port = (self.port is None) while time.time() < end_at: # We have had problems with port conflicts on travis # so we will try a different port on each retry # unless the fixture was passed a specific port if auto_port: self.port = get_open_port() self.out('Attempting to start on port %d (try #%d)' % (self.port, tries)) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"\[Kafka Server %d\], Started" % self.broker_id, timeout=timeout): break self.child.dump_logs() self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 else: raise Exception('Failed to start KafkaInstance before max_timeout') self.out("Done!") self.running = True atexit.register(self.close)
def open(self): if self.running: self.out("Instance already running") return self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port) log.info(" broker_id = %s", self.broker_id) log.info(" zk_host = %s", self.zk_host) log.info(" zk_port = %s", self.zk_port) log.info(" zk_chroot = %s", self.zk_chroot) log.info(" replicas = %s", self.replicas) log.info(" partitions = %s", self.partitions) log.info(" tmp_dir = %s", self.tmp_dir) # Create directories os.mkdir(os.path.join(self.tmp_dir, "logs")) os.mkdir(os.path.join(self.tmp_dir, "data")) # Generate configs template = self.test_resource("kafka.properties") properties = os.path.join(self.tmp_dir, "kafka.properties") self.render_template(template, properties, vars(self)) # Party! self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args( "org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zk_host, self.zk_port), "create", "/%s" % self.zk_chroot, "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if proc.wait() != 0: self.out("Failed to create Zookeeper chroot node") self.out(proc.stdout.read()) self.out(proc.stderr.read()) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Done!") # Configure Kafka child process args = self.kafka_run_class_args("kafka.Kafka", properties) env = self.kafka_run_class_env() timeout = 5 max_timeout = 30 backoff = 1 end_at = time.time() + max_timeout tries = 1 while time.time() < end_at: self.out('Attempting to start (try #%d)' % tries) try: os.stat(properties) except: log.warning('Config %s not found -- re-rendering', properties) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"\[Kafka Server %d\], Started" % self.broker_id, timeout=timeout): break self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 else: raise Exception('Failed to start KafkaInstance before max_timeout') self.out("Done!") self.running = True atexit.register(self.close)
class KafkaFixture(Fixture): @classmethod def instance(cls, broker_id, zk_host, zk_port, zk_chroot=None, port=None, transport='PLAINTEXT', replicas=1, partitions=2): if zk_chroot is None: zk_chroot = "kafka-python_" + str(uuid.uuid4()).replace("-", "_") if "KAFKA_URI" in os.environ: parse = urlparse(os.environ["KAFKA_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: if port is None: port = get_open_port() host = "127.0.0.1" fixture = KafkaFixture(host, port, broker_id, zk_host, zk_port, zk_chroot, transport=transport, replicas=replicas, partitions=partitions) fixture.open() return fixture def __init__(self, host, port, broker_id, zk_host, zk_port, zk_chroot, replicas=1, partitions=2, transport='PLAINTEXT'): self.host = host self.port = port self.broker_id = broker_id self.transport = transport.upper() self.ssl_dir = self.test_resource('ssl') self.zk_host = zk_host self.zk_port = zk_port self.zk_chroot = zk_chroot self.replicas = replicas self.partitions = partitions self.tmp_dir = None self.child = None self.running = False def kafka_run_class_env(self): env = super(KafkaFixture, self).kafka_run_class_env() env['LOG_DIR'] = os.path.join(self.tmp_dir, 'logs') return env def out(self, message): log.info("*** Kafka [%s:%d]: %s", self.host, self.port, message) def open(self): if self.running: self.out("Instance already running") return self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port) log.info(" transport = %s", self.transport) log.info(" broker_id = %s", self.broker_id) log.info(" zk_host = %s", self.zk_host) log.info(" zk_port = %s", self.zk_port) log.info(" zk_chroot = %s", self.zk_chroot) log.info(" replicas = %s", self.replicas) log.info(" partitions = %s", self.partitions) log.info(" tmp_dir = %s", self.tmp_dir) # Create directories os.mkdir(os.path.join(self.tmp_dir, "logs")) os.mkdir(os.path.join(self.tmp_dir, "data")) # Generate configs template = self.test_resource("kafka.properties") properties = os.path.join(self.tmp_dir, "kafka.properties") self.render_template(template, properties, vars(self)) # Party! self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args( "org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zk_host, self.zk_port), "create", "/%s" % self.zk_chroot, "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if proc.wait() != 0: self.out("Failed to create Zookeeper chroot node") self.out(proc.stdout.read()) self.out(proc.stderr.read()) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Done!") # Configure Kafka child process args = self.kafka_run_class_args("kafka.Kafka", properties) env = self.kafka_run_class_env() timeout = 5 max_timeout = 30 backoff = 1 end_at = time.time() + max_timeout tries = 1 while time.time() < end_at: self.out('Attempting to start (try #%d)' % tries) try: os.stat(properties) except: log.warning('Config %s not found -- re-rendering', properties) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"\[Kafka Server %d\], Started" % self.broker_id, timeout=timeout): break self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 else: raise Exception('Failed to start KafkaInstance before max_timeout') self.out("Done!") self.running = True atexit.register(self.close) def __del__(self): self.close() def close(self): if not self.running: self.out("Instance already stopped") return self.out("Stopping...") self.child.stop() self.child = None self.out("Done!") shutil.rmtree(self.tmp_dir) self.running = False
class KafkaFixture(Fixture): @classmethod def instance(cls, broker_id, zookeeper, zk_chroot=None, host=None, port=None, transport='PLAINTEXT', replicas=1, partitions=2, sasl_mechanism='PLAIN', auto_create_topic=True, tmp_dir=None): if zk_chroot is None: zk_chroot = "kafka-python_" + str(uuid.uuid4()).replace("-", "_") if "KAFKA_URI" in os.environ: parse = urlparse(os.environ["KAFKA_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: if host is None: host = "localhost" fixture = KafkaFixture(host, port, broker_id, zookeeper, zk_chroot, transport=transport, replicas=replicas, partitions=partitions, sasl_mechanism=sasl_mechanism, auto_create_topic=auto_create_topic, tmp_dir=tmp_dir) fixture.open() return fixture def __init__(self, host, port, broker_id, zookeeper, zk_chroot, replicas=1, partitions=2, transport='PLAINTEXT', sasl_mechanism='PLAIN', auto_create_topic=True, tmp_dir=None): super(KafkaFixture, self).__init__() self.host = host self.port = port self.broker_id = broker_id self.auto_create_topic = auto_create_topic self.transport = transport.upper() self.sasl_mechanism = sasl_mechanism.upper() self.ssl_dir = self.test_resource('ssl') # TODO: checking for port connection would be better than scanning logs # until then, we need the pattern to work across all supported broker versions # The logging format changed slightly in 1.0.0 self.start_pattern = r"\[Kafka ?Server (id=)?%d\],? started" % ( broker_id, ) self.zookeeper = zookeeper self.zk_chroot = zk_chroot # Add the attributes below for the template binding self.zk_host = self.zookeeper.host self.zk_port = self.zookeeper.port self.replicas = replicas self.partitions = partitions self.tmp_dir = tmp_dir self.running = False self._client = None def bootstrap_server(self): return '%s:%d' % (self.host, self.port) def kafka_run_class_env(self): env = super(KafkaFixture, self).kafka_run_class_env() env['LOG_DIR'] = self.tmp_dir.join('logs').strpath return env def out(self, message): log.info("*** Kafka [%s:%s]: %s", self.host, self.port or '(auto)', message) def _create_zk_chroot(self): self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args( "org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zookeeper.host, self.zookeeper.port), "create", "/%s" % (self.zk_chroot, ), "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communicate() if proc.returncode != 0: self.out("Failed to create Zookeeper chroot node") self.out(stdout) self.out(stderr) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Kafka chroot created in Zookeeper!") def start(self): # Configure Kafka child process properties = self.tmp_dir.join("kafka.properties") template = self.test_resource("kafka.properties") args = self.kafka_run_class_args("kafka.Kafka", properties.strpath) env = self.kafka_run_class_env() timeout = 5 max_timeout = 120 backoff = 1 end_at = time.time() + max_timeout tries = 1 auto_port = (self.port is None) while time.time() < end_at: # We have had problems with port conflicts on travis # so we will try a different port on each retry # unless the fixture was passed a specific port if auto_port: self.port = get_open_port() self.out('Attempting to start on port %d (try #%d)' % (self.port, tries)) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(self.start_pattern, timeout=timeout): break self.child.dump_logs() self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 backoff += 1 else: raise RuntimeError( 'Failed to start KafkaInstance before max_timeout') (self._client, ) = self.get_clients(1, '_internal_client') self.out("Done!") self.running = True def open(self): if self.running: self.out("Instance already running") return # Create directories if self.tmp_dir is None: self.tmp_dir = py.path.local.mkdtemp() #pylint: disable=no-member self.tmp_dir.ensure(dir=True) self.tmp_dir.ensure('logs', dir=True) self.tmp_dir.ensure('data', dir=True) self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port or '(auto)') log.info(" transport = %s", self.transport) log.info(" broker_id = %s", self.broker_id) log.info(" zk_host = %s", self.zookeeper.host) log.info(" zk_port = %s", self.zookeeper.port) log.info(" zk_chroot = %s", self.zk_chroot) log.info(" replicas = %s", self.replicas) log.info(" partitions = %s", self.partitions) log.info(" tmp_dir = %s", self.tmp_dir.strpath) self._create_zk_chroot() self.start() atexit.register(self.close) def __del__(self): self.close() def stop(self): if not self.running: self.out("Instance already stopped") return self.out("Stopping...") self.child.stop() self.child = None self.running = False self.out("Stopped!") def close(self): self.stop() if self.tmp_dir is not None: self.tmp_dir.remove() self.tmp_dir = None self.out("Done!") def dump_logs(self): super(KafkaFixture, self).dump_logs() self.zookeeper.dump_logs() def _send_request(self, request, timeout=None): def _failure(error): raise error retries = 10 while True: node_id = self._client.least_loaded_node() for connect_retry in range(40): self._client.maybe_connect(node_id) if self._client.connected(node_id): break self._client.poll(timeout_ms=100) else: raise RuntimeError( 'Could not connect to broker with node id %d' % (node_id, )) try: future = self._client.send(node_id, request) future.error_on_callbacks = True future.add_errback(_failure) return self._client.poll(future=future, timeout_ms=timeout) except Exception as exc: time.sleep(1) retries -= 1 if retries == 0: raise exc else: pass # retry def _create_topic(self, topic_name, num_partitions, replication_factor, timeout_ms=10000): if num_partitions is None: num_partitions = self.partitions if replication_factor is None: replication_factor = self.replicas # Try different methods to create a topic, from the fastest to the slowest if self.auto_create_topic and \ num_partitions == self.partitions and \ replication_factor == self.replicas: self._send_request(MetadataRequest[0]([topic_name])) elif version() >= (0, 10, 1, 0): request = CreateTopicsRequest[0]( [(topic_name, num_partitions, replication_factor, [], [])], timeout_ms) result = self._send_request(request, timeout=timeout_ms) for topic_result in result[0].topic_error_codes: error_code = topic_result[1] if error_code != 0: raise errors.for_code(error_code) else: args = self.kafka_run_class_args('kafka.admin.TopicCommand', '--zookeeper', '%s:%s/%s' % (self.zookeeper.host, self.zookeeper.port, self.zk_chroot), '--create', '--topic', topic_name, '--partitions', self.partitions \ if num_partitions is None else num_partitions, '--replication-factor', self.replicas \ if replication_factor is None \ else replication_factor) if version() >= (0, 10): args.append('--if-not-exists') env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communicate() if proc.returncode != 0: if 'kafka.common.TopicExistsException' not in stdout: self.out("Failed to create topic %s" % (topic_name, )) self.out(stdout) self.out(stderr) raise RuntimeError("Failed to create topic %s" % (topic_name, )) def create_topics(self, topic_names, num_partitions=None, replication_factor=None): for topic_name in topic_names: self._create_topic(topic_name, num_partitions, replication_factor) def get_clients(self, cnt=1, client_id=None): if client_id is None: client_id = 'client' return tuple( KafkaClient(client_id='%s_%s' % (client_id, random_string(4)), bootstrap_servers=self.bootstrap_server()) for x in range(cnt)) def get_consumers(self, cnt, topics, **params): params.setdefault('client_id', 'consumer') params.setdefault('heartbeat_interval_ms', 500) params['bootstrap_servers'] = self.bootstrap_server() client_id = params['client_id'] for x in range(cnt): params['client_id'] = '%s_%s' % (client_id, random_string(4)) yield KafkaConsumer(*topics, **params) def get_producers(self, cnt, **params): params.setdefault('client_id', 'producer') params['bootstrap_servers'] = self.bootstrap_server() client_id = params['client_id'] for x in range(cnt): params['client_id'] = '%s_%s' % (client_id, random_string(4)) yield KafkaProducer(**params) def get_simple_client(self, **params): params.setdefault('client_id', 'simple_client') return SimpleClient(self.bootstrap_server(), **params)
class ZookeeperFixture(Fixture): @classmethod def instance(cls): if "ZOOKEEPER_URI" in os.environ: parse = urlparse(os.environ["ZOOKEEPER_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: (host, port) = ("127.0.0.1", get_open_port()) fixture = cls(host, port) fixture.open() return fixture def __init__(self, host, port): self.host = host self.port = port self.tmp_dir = None self.child = None def kafka_run_class_env(self): env = super(ZookeeperFixture, self).kafka_run_class_env() env['LOG_DIR'] = os.path.join(self.tmp_dir, 'logs') return env def out(self, message): log.info("*** Zookeeper [%s:%d]: %s", self.host, self.port, message) def open(self): self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port) log.info(" tmp_dir = %s", self.tmp_dir) # Generate configs template = self.test_resource("zookeeper.properties") properties = os.path.join(self.tmp_dir, "zookeeper.properties") self.render_template(template, properties, vars(self)) # Configure Zookeeper child process args = self.kafka_run_class_args("org.apache.zookeeper.server.quorum.QuorumPeerMain", properties) env = self.kafka_run_class_env() # Party! timeout = 5 max_timeout = 30 backoff = 1 end_at = time.time() + max_timeout tries = 1 while time.time() < end_at: self.out('Attempting to start (try #%d)' % tries) try: os.stat(properties) except: log.warning('Config %s not found -- re-rendering', properties) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"binding to port", timeout=timeout): break self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 else: raise Exception('Failed to start Zookeeper before max_timeout') self.out("Done!") atexit.register(self.close) def close(self): if self.child is None: return self.out("Stopping...") self.child.stop() self.child = None self.out("Done!") shutil.rmtree(self.tmp_dir) def __del__(self): self.close()
def open(self): if self.running: self.out("Instance already running") return self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port) log.info(" transport = %s", self.transport) log.info(" broker_id = %s", self.broker_id) log.info(" zk_host = %s", self.zk_host) log.info(" zk_port = %s", self.zk_port) log.info(" zk_chroot = %s", self.zk_chroot) log.info(" replicas = %s", self.replicas) log.info(" partitions = %s", self.partitions) log.info(" tmp_dir = %s", self.tmp_dir) # Create directories os.mkdir(os.path.join(self.tmp_dir, "logs")) os.mkdir(os.path.join(self.tmp_dir, "data")) # Generate configs template = self.test_resource("kafka.properties") properties = os.path.join(self.tmp_dir, "kafka.properties") self.render_template(template, properties, vars(self)) # Party! self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args("org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zk_host, self.zk_port), "create", "/%s" % self.zk_chroot, "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if proc.wait() != 0: self.out("Failed to create Zookeeper chroot node") self.out(proc.stdout.read()) self.out(proc.stderr.read()) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Done!") # Configure Kafka child process args = self.kafka_run_class_args("kafka.Kafka", properties) env = self.kafka_run_class_env() timeout = 5 max_timeout = 30 backoff = 1 end_at = time.time() + max_timeout tries = 1 while time.time() < end_at: self.out('Attempting to start (try #%d)' % tries) try: os.stat(properties) except: log.warning('Config %s not found -- re-rendering', properties) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"\[Kafka Server %d\], Started" % self.broker_id, timeout=timeout): break self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 else: raise Exception('Failed to start KafkaInstance before max_timeout') self.out("Done!") self.running = True atexit.register(self.close)
class KafkaFixture(Fixture): @classmethod def instance(cls, broker_id, zk_host, zk_port, zk_chroot=None, host=None, port=None, transport='PLAINTEXT', replicas=1, partitions=2): if zk_chroot is None: zk_chroot = "kafka-python_" + str(uuid.uuid4()).replace("-", "_") if "KAFKA_URI" in os.environ: parse = urlparse(os.environ["KAFKA_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: if host is None: host = "localhost" fixture = KafkaFixture(host, port, broker_id, zk_host, zk_port, zk_chroot, transport=transport, replicas=replicas, partitions=partitions) fixture.open() return fixture def __init__(self, host, port, broker_id, zk_host, zk_port, zk_chroot, replicas=1, partitions=2, transport='PLAINTEXT'): self.host = host self.port = port self.broker_id = broker_id self.transport = transport.upper() self.ssl_dir = self.test_resource('ssl') # TODO: checking for port connection would be better than scanning logs # until then, we need the pattern to work across all supported broker versions # The logging format changed slightly in 1.0.0 self.start_pattern = r"\[Kafka ?Server (id=)?%d\],? started" % broker_id self.zk_host = zk_host self.zk_port = zk_port self.zk_chroot = zk_chroot self.replicas = replicas self.partitions = partitions self.tmp_dir = None self.child = None self.running = False def kafka_run_class_env(self): env = super(KafkaFixture, self).kafka_run_class_env() env['LOG_DIR'] = os.path.join(self.tmp_dir, 'logs') return env def out(self, message): log.info("*** Kafka [%s:%s]: %s", self.host, self.port or '(auto)', message) def open(self): if self.running: self.out("Instance already running") return self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port or '(auto)') log.info(" transport = %s", self.transport) log.info(" broker_id = %s", self.broker_id) log.info(" zk_host = %s", self.zk_host) log.info(" zk_port = %s", self.zk_port) log.info(" zk_chroot = %s", self.zk_chroot) log.info(" replicas = %s", self.replicas) log.info(" partitions = %s", self.partitions) log.info(" tmp_dir = %s", self.tmp_dir) # Create directories os.mkdir(os.path.join(self.tmp_dir, "logs")) os.mkdir(os.path.join(self.tmp_dir, "data")) self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args( "org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zk_host, self.zk_port), "create", "/%s" % self.zk_chroot, "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if proc.wait() != 0: self.out("Failed to create Zookeeper chroot node") self.out(proc.stdout.read()) self.out(proc.stderr.read()) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Done!") # Configure Kafka child process properties = os.path.join(self.tmp_dir, "kafka.properties") template = self.test_resource("kafka.properties") args = self.kafka_run_class_args("kafka.Kafka", properties) env = self.kafka_run_class_env() timeout = 5 max_timeout = 30 backoff = 1 end_at = time.time() + max_timeout tries = 1 auto_port = (self.port is None) while time.time() < end_at: # We have had problems with port conflicts on travis # so we will try a different port on each retry # unless the fixture was passed a specific port if auto_port: self.port = get_open_port() self.out('Attempting to start on port %d (try #%d)' % (self.port, tries)) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(self.start_pattern, timeout=timeout): break self.child.dump_logs() self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 else: raise Exception('Failed to start KafkaInstance before max_timeout') self.out("Done!") self.running = True atexit.register(self.close) def __del__(self): self.close() def close(self): if not self.running: self.out("Instance already stopped") return self.out("Stopping...") self.child.stop() self.child = None self.out("Done!") shutil.rmtree(self.tmp_dir) self.running = False
class ZookeeperFixture(Fixture): @classmethod def instance(cls): if "ZOOKEEPER_URI" in os.environ: parse = urlparse(os.environ["ZOOKEEPER_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: (host, port) = ("127.0.0.1", get_open_port()) fixture = cls(host, port) fixture.open() return fixture def __init__(self, host, port): self.host = host self.port = port self.tmp_dir = None self.child = None def kafka_run_class_env(self): env = super(ZookeeperFixture, self).kafka_run_class_env() env['LOG_DIR'] = os.path.join(self.tmp_dir, 'logs') return env def out(self, message): log.info("*** Zookeeper [%s:%d]: %s", self.host, self.port, message) def open(self): self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port) log.info(" tmp_dir = %s", self.tmp_dir) # Generate configs template = self.test_resource("zookeeper.properties") properties = os.path.join(self.tmp_dir, "zookeeper.properties") self.render_template(template, properties, vars(self)) # Configure Zookeeper child process args = self.kafka_run_class_args( "org.apache.zookeeper.server.quorum.QuorumPeerMain", properties) env = self.kafka_run_class_env() # Party! timeout = 5 max_timeout = 30 backoff = 1 end_at = time.time() + max_timeout tries = 1 while time.time() < end_at: self.out('Attempting to start (try #%d)' % tries) try: os.stat(properties) except: log.warning('Config %s not found -- re-rendering', properties) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"binding to port", timeout=timeout): break self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 else: raise Exception('Failed to start Zookeeper before max_timeout') self.out("Done!") atexit.register(self.close) def close(self): if self.child is None: return self.out("Stopping...") self.child.stop() self.child = None self.out("Done!") shutil.rmtree(self.tmp_dir) def __del__(self): self.close()
class KafkaFixture(Fixture): @classmethod def instance(cls, broker_id, zookeeper, zk_chroot=None, host=None, port=None, transport='PLAINTEXT', replicas=1, partitions=2, sasl_mechanism='PLAIN', auto_create_topic=True, tmp_dir=None): if zk_chroot is None: zk_chroot = "kafka-python_" + str(uuid.uuid4()).replace("-", "_") if "KAFKA_URI" in os.environ: parse = urlparse(os.environ["KAFKA_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: if host is None: host = "localhost" fixture = KafkaFixture(host, port, broker_id, zookeeper, zk_chroot, transport=transport, replicas=replicas, partitions=partitions, sasl_mechanism=sasl_mechanism, auto_create_topic=auto_create_topic, tmp_dir=tmp_dir) fixture.open() return fixture def __init__(self, host, port, broker_id, zookeeper, zk_chroot, replicas=1, partitions=2, transport='PLAINTEXT', sasl_mechanism='PLAIN', auto_create_topic=True, tmp_dir=None): super(KafkaFixture, self).__init__() self.host = host self.port = port self.broker_id = broker_id self.auto_create_topic = auto_create_topic self.transport = transport.upper() self.sasl_mechanism = sasl_mechanism.upper() self.ssl_dir = self.test_resource('ssl') # TODO: checking for port connection would be better than scanning logs # until then, we need the pattern to work across all supported broker versions # The logging format changed slightly in 1.0.0 self.start_pattern = r"\[Kafka ?Server (id=)?%d\],? started" % broker_id self.zookeeper = zookeeper self.zk_chroot = zk_chroot # Add the attributes below for the template binding self.zk_host = self.zookeeper.host self.zk_port = self.zookeeper.port self.replicas = replicas self.partitions = partitions self.tmp_dir = tmp_dir self.running = False self._client = None def bootstrap_server(self): return '%s:%d' % (self.host, self.port) def kafka_run_class_env(self): env = super(KafkaFixture, self).kafka_run_class_env() env['LOG_DIR'] = self.tmp_dir.join('logs').strpath return env def out(self, message): log.info("*** Kafka [%s:%s]: %s", self.host, self.port or '(auto)', message) def _create_zk_chroot(self): self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args("org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zookeeper.host, self.zookeeper.port), "create", "/%s" % self.zk_chroot, "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if proc.wait() != 0 or proc.returncode != 0: self.out("Failed to create Zookeeper chroot node") self.out(proc.stdout.read()) self.out(proc.stderr.read()) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Kafka chroot created in Zookeeper!") def start(self): # Configure Kafka child process properties = self.tmp_dir.join("kafka.properties") template = self.test_resource("kafka.properties") args = self.kafka_run_class_args("kafka.Kafka", properties.strpath) env = self.kafka_run_class_env() timeout = 5 max_timeout = 120 backoff = 1 end_at = time.time() + max_timeout tries = 1 auto_port = (self.port is None) while time.time() < end_at: # We have had problems with port conflicts on travis # so we will try a different port on each retry # unless the fixture was passed a specific port if auto_port: self.port = get_open_port() self.out('Attempting to start on port %d (try #%d)' % (self.port, tries)) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(self.start_pattern, timeout=timeout): break self.child.dump_logs() self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 backoff += 1 else: raise RuntimeError('Failed to start KafkaInstance before max_timeout') (self._client,) = self.get_clients(1, '_internal_client') self.out("Done!") self.running = True def open(self): if self.running: self.out("Instance already running") return # Create directories if self.tmp_dir is None: self.tmp_dir = py.path.local.mkdtemp() #pylint: disable=no-member self.tmp_dir.ensure(dir=True) self.tmp_dir.ensure('logs', dir=True) self.tmp_dir.ensure('data', dir=True) self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port or '(auto)') log.info(" transport = %s", self.transport) log.info(" broker_id = %s", self.broker_id) log.info(" zk_host = %s", self.zookeeper.host) log.info(" zk_port = %s", self.zookeeper.port) log.info(" zk_chroot = %s", self.zk_chroot) log.info(" replicas = %s", self.replicas) log.info(" partitions = %s", self.partitions) log.info(" tmp_dir = %s", self.tmp_dir.strpath) self._create_zk_chroot() self.start() atexit.register(self.close) def __del__(self): self.close() def stop(self): if not self.running: self.out("Instance already stopped") return self.out("Stopping...") self.child.stop() self.child = None self.running = False self.out("Stopped!") def close(self): self.stop() if self.tmp_dir is not None: self.tmp_dir.remove() self.tmp_dir = None self.out("Done!") def dump_logs(self): super(KafkaFixture, self).dump_logs() self.zookeeper.dump_logs() def _send_request(self, request, timeout=None): def _failure(error): raise error retries = 10 while True: node_id = self._client.least_loaded_node() for ready_retry in range(40): if self._client.ready(node_id, False): break time.sleep(.1) else: raise RuntimeError('Could not connect to broker with node id %d' % (node_id,)) try: future = self._client.send(node_id, request) future.error_on_callbacks = True future.add_errback(_failure) return self._client.poll(future=future, timeout_ms=timeout) except Exception as exc: time.sleep(1) retries -= 1 if retries == 0: raise exc else: pass # retry def _create_topic(self, topic_name, num_partitions, replication_factor, timeout_ms=10000): if num_partitions is None: num_partitions = self.partitions if replication_factor is None: replication_factor = self.replicas # Try different methods to create a topic, from the fastest to the slowest if self.auto_create_topic and \ num_partitions == self.partitions and \ replication_factor == self.replicas: self._send_request(MetadataRequest[0]([topic_name])) elif version() >= (0, 10, 1, 0): request = CreateTopicsRequest[0]([(topic_name, num_partitions, replication_factor, [], [])], timeout_ms) result = self._send_request(request, timeout=timeout_ms) for topic_result in result[0].topic_error_codes: error_code = topic_result[1] if error_code != 0: raise errors.for_code(error_code) else: args = self.kafka_run_class_args('kafka.admin.TopicCommand', '--zookeeper', '%s:%s/%s' % (self.zookeeper.host, self.zookeeper.port, self.zk_chroot), '--create', '--topic', topic_name, '--partitions', self.partitions \ if num_partitions is None else num_partitions, '--replication-factor', self.replicas \ if replication_factor is None \ else replication_factor) if version() >= (0, 10): args.append('--if-not-exists') env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) ret = proc.wait() if ret != 0 or proc.returncode != 0: output = proc.stdout.read() if not 'kafka.common.TopicExistsException' in output: self.out("Failed to create topic %s" % (topic_name,)) self.out(output) self.out(proc.stderr.read()) raise RuntimeError("Failed to create topic %s" % (topic_name,)) def create_topics(self, topic_names, num_partitions=None, replication_factor=None): for topic_name in topic_names: self._create_topic(topic_name, num_partitions, replication_factor) def get_clients(self, cnt=1, client_id=None): if client_id is None: client_id = 'client' return tuple(KafkaClient(client_id='%s_%s' % (client_id, random_string(4)), bootstrap_servers=self.bootstrap_server()) for x in range(cnt)) def get_consumers(self, cnt, topics, **params): params.setdefault('client_id', 'consumer') params.setdefault('heartbeat_interval_ms', 500) params['bootstrap_servers'] = self.bootstrap_server() client_id = params['client_id'] for x in range(cnt): params['client_id'] = '%s_%s' % (client_id, random_string(4)) yield KafkaConsumer(*topics, **params) def get_producers(self, cnt, **params): params.setdefault('client_id', 'producer') params['bootstrap_servers'] = self.bootstrap_server() client_id = params['client_id'] for x in range(cnt): params['client_id'] = '%s_%s' % (client_id, random_string(4)) yield KafkaProducer(**params) def get_simple_client(self, **params): params.setdefault('client_id', 'simple_client') return SimpleClient(self.bootstrap_server(), **params)
class KafkaFixture(Fixture): @classmethod def instance(cls, broker_id, zk_host, zk_port, zk_chroot=None, host=None, port=None, transport='PLAINTEXT', replicas=1, partitions=2): if zk_chroot is None: zk_chroot = "kafka-python_" + str(uuid.uuid4()).replace("-", "_") if "KAFKA_URI" in os.environ: parse = urlparse(os.environ["KAFKA_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: # force IPv6 here because of a confusing point: # # - if the string "localhost" is passed, Kafka will *only* bind to the IPv4 address of localhost # (127.0.0.1); however, kafka-python will attempt to connect on ::1 and fail # # - if the address literal 127.0.0.1 is passed, the metadata request during bootstrap will return # the name "localhost" and we'll go back to the first case. This is odd! # # Ideally, Kafka would bind to all loopback addresses when we tell it to listen on "localhost" the # way it makes an IPv6 socket bound to both 0.0.0.0/0 and ::/0 when we tell it to bind to "" (that is # to say, when we make a listener of PLAINTEXT://:port. # # Note that even though we specify the bind host in bracket notation, Kafka responds to the bootstrap # metadata request without square brackets later. if host is None: host = "[::1]" fixture = KafkaFixture(host, port, broker_id, zk_host, zk_port, zk_chroot, transport=transport, replicas=replicas, partitions=partitions) fixture.open() return fixture def __init__(self, host, port, broker_id, zk_host, zk_port, zk_chroot, replicas=1, partitions=2, transport='PLAINTEXT'): self.host = host self.port = port self.broker_id = broker_id self.transport = transport.upper() self.ssl_dir = self.test_resource('ssl') self.zk_host = zk_host self.zk_port = zk_port self.zk_chroot = zk_chroot self.replicas = replicas self.partitions = partitions self.tmp_dir = None self.child = None self.running = False def kafka_run_class_env(self): env = super(KafkaFixture, self).kafka_run_class_env() env['LOG_DIR'] = os.path.join(self.tmp_dir, 'logs') return env def out(self, message): log.info("*** Kafka [%s:%s]: %s", self.host, self.port or '(auto)', message) def open(self): if self.running: self.out("Instance already running") return self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port or '(auto)') log.info(" transport = %s", self.transport) log.info(" broker_id = %s", self.broker_id) log.info(" zk_host = %s", self.zk_host) log.info(" zk_port = %s", self.zk_port) log.info(" zk_chroot = %s", self.zk_chroot) log.info(" replicas = %s", self.replicas) log.info(" partitions = %s", self.partitions) log.info(" tmp_dir = %s", self.tmp_dir) # Create directories os.mkdir(os.path.join(self.tmp_dir, "logs")) os.mkdir(os.path.join(self.tmp_dir, "data")) self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args( "org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zk_host, self.zk_port), "create", "/%s" % self.zk_chroot, "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if proc.wait() != 0: self.out("Failed to create Zookeeper chroot node") self.out(proc.stdout.read()) self.out(proc.stderr.read()) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Done!") # Configure Kafka child process properties = os.path.join(self.tmp_dir, "kafka.properties") template = self.test_resource("kafka.properties") args = self.kafka_run_class_args("kafka.Kafka", properties) env = self.kafka_run_class_env() timeout = 5 max_timeout = 30 backoff = 1 end_at = time.time() + max_timeout tries = 1 auto_port = (self.port is None) while time.time() < end_at: # We have had problems with port conflicts on travis # so we will try a different port on each retry # unless the fixture was passed a specific port if auto_port: self.port = get_open_port() self.out('Attempting to start on port %d (try #%d)' % (self.port, tries)) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"\[Kafka Server %d\], Started" % self.broker_id, timeout=timeout): break self.child.dump_logs() self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 else: raise Exception('Failed to start KafkaInstance before max_timeout') self.out("Done!") self.running = True atexit.register(self.close) def __del__(self): self.close() def close(self): if not self.running: self.out("Instance already stopped") return self.out("Stopping...") self.child.stop() self.child = None self.out("Done!") shutil.rmtree(self.tmp_dir) self.running = False
class KafkaFixture(Fixture): @classmethod def instance(cls, broker_id, zk_host, zk_port, zk_chroot=None, host=None, port=None, transport='PLAINTEXT', replicas=1, partitions=2): if zk_chroot is None: zk_chroot = "kafka-python_" + str(uuid.uuid4()).replace("-", "_") if "KAFKA_URI" in os.environ: parse = urlparse(os.environ["KAFKA_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: if port is None: port = get_open_port() # force IPv6 here because of a confusing point: # # - if the string "localhost" is passed, Kafka will *only* bind to the IPv4 address of localhost # (127.0.0.1); however, kafka-python will attempt to connect on ::1 and fail # # - if the address literal 127.0.0.1 is passed, the metadata request during bootstrap will return # the name "localhost" and we'll go back to the first case. This is odd! # # Ideally, Kafka would bind to all loopback addresses when we tell it to listen on "localhost" the # way it makes an IPv6 socket bound to both 0.0.0.0/0 and ::/0 when we tell it to bind to "" (that is # to say, when we make a listener of PLAINTEXT://:port. # # Note that even though we specify the bind host in bracket notation, Kafka responds to the bootstrap # metadata request without square brackets later. if host is None: host = "[::1]" fixture = KafkaFixture(host, port, broker_id, zk_host, zk_port, zk_chroot, transport=transport, replicas=replicas, partitions=partitions) fixture.open() return fixture def __init__(self, host, port, broker_id, zk_host, zk_port, zk_chroot, replicas=1, partitions=2, transport='PLAINTEXT'): self.host = host self.port = port self.broker_id = broker_id self.transport = transport.upper() self.ssl_dir = self.test_resource('ssl') self.zk_host = zk_host self.zk_port = zk_port self.zk_chroot = zk_chroot self.replicas = replicas self.partitions = partitions self.tmp_dir = None self.child = None self.running = False def kafka_run_class_env(self): env = super(KafkaFixture, self).kafka_run_class_env() env['LOG_DIR'] = os.path.join(self.tmp_dir, 'logs') return env def out(self, message): log.info("*** Kafka [%s:%d]: %s", self.host, self.port, message) def open(self): if self.running: self.out("Instance already running") return self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port) log.info(" transport = %s", self.transport) log.info(" broker_id = %s", self.broker_id) log.info(" zk_host = %s", self.zk_host) log.info(" zk_port = %s", self.zk_port) log.info(" zk_chroot = %s", self.zk_chroot) log.info(" replicas = %s", self.replicas) log.info(" partitions = %s", self.partitions) log.info(" tmp_dir = %s", self.tmp_dir) # Create directories os.mkdir(os.path.join(self.tmp_dir, "logs")) os.mkdir(os.path.join(self.tmp_dir, "data")) # Generate configs template = self.test_resource("kafka.properties") properties = os.path.join(self.tmp_dir, "kafka.properties") self.render_template(template, properties, vars(self)) # Party! self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args("org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zk_host, self.zk_port), "create", "/%s" % self.zk_chroot, "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if proc.wait() != 0: self.out("Failed to create Zookeeper chroot node") self.out(proc.stdout.read()) self.out(proc.stderr.read()) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Done!") # Configure Kafka child process args = self.kafka_run_class_args("kafka.Kafka", properties) env = self.kafka_run_class_env() timeout = 5 max_timeout = 30 backoff = 1 end_at = time.time() + max_timeout tries = 1 while time.time() < end_at: self.out('Attempting to start (try #%d)' % tries) try: os.stat(properties) except: log.warning('Config %s not found -- re-rendering', properties) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"\[Kafka Server %d\], Started" % self.broker_id, timeout=timeout): break self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 else: raise Exception('Failed to start KafkaInstance before max_timeout') self.out("Done!") self.running = True atexit.register(self.close) def __del__(self): self.close() def close(self): if not self.running: self.out("Instance already stopped") return self.out("Stopping...") self.child.stop() self.child = None self.out("Done!") shutil.rmtree(self.tmp_dir) self.running = False
class KafkaFixture(Fixture): @classmethod def instance(cls, broker_id, zk_host, zk_port, zk_chroot=None, port=None, replicas=1, partitions=2): if zk_chroot is None: zk_chroot = "kafka-python_" + str(uuid.uuid4()).replace("-", "_") if "KAFKA_URI" in os.environ: parse = urlparse(os.environ["KAFKA_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: if port is None: port = get_open_port() host = "127.0.0.1" fixture = KafkaFixture(host, port, broker_id, zk_host, zk_port, zk_chroot, replicas=replicas, partitions=partitions) fixture.open() return fixture def __init__(self, host, port, broker_id, zk_host, zk_port, zk_chroot, replicas=1, partitions=2): self.host = host self.port = port self.broker_id = broker_id self.zk_host = zk_host self.zk_port = zk_port self.zk_chroot = zk_chroot self.replicas = replicas self.partitions = partitions self.tmp_dir = None self.child = None self.running = False def out(self, message): log.info("*** Kafka [%s:%d]: %s", self.host, self.port, message) def open(self): if self.running: self.out("Instance already running") return self.tmp_dir = tempfile.mkdtemp() self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port) log.info(" broker_id = %s", self.broker_id) log.info(" zk_host = %s", self.zk_host) log.info(" zk_port = %s", self.zk_port) log.info(" zk_chroot = %s", self.zk_chroot) log.info(" replicas = %s", self.replicas) log.info(" partitions = %s", self.partitions) log.info(" tmp_dir = %s", self.tmp_dir) # Create directories os.mkdir(os.path.join(self.tmp_dir, "logs")) os.mkdir(os.path.join(self.tmp_dir, "data")) # Generate configs template = self.test_resource("kafka.properties") properties = os.path.join(self.tmp_dir, "kafka.properties") self.render_template(template, properties, vars(self)) # Party! self.out("Creating Zookeeper chroot node...") args = self.kafka_run_class_args("org.apache.zookeeper.ZooKeeperMain", "-server", "%s:%d" % (self.zk_host, self.zk_port), "create", "/%s" % self.zk_chroot, "kafka-python") env = self.kafka_run_class_env() proc = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if proc.wait() != 0: self.out("Failed to create Zookeeper chroot node") self.out(proc.stdout.read()) self.out(proc.stderr.read()) raise RuntimeError("Failed to create Zookeeper chroot node") self.out("Done!") self.out("Starting...") # Configure Kafka child process args = self.kafka_run_class_args("kafka.Kafka", properties) env = self.kafka_run_class_env() timeout = 5 max_timeout = 30 backoff = 1 while True: self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max_timeout) if self.child.wait_for(r"\[Kafka Server %d\], Started" % self.broker_id, timeout=timeout): break self.child.stop() timeout *= 2 time.sleep(backoff) self.out("Done!") self.running = True def close(self): if not self.running: self.out("Instance already stopped") return self.out("Stopping...") self.child.stop() self.child = None self.out("Done!") shutil.rmtree(self.tmp_dir) self.running = False
class ZookeeperFixture(Fixture): @classmethod def instance(cls): if "ZOOKEEPER_URI" in os.environ: parse = urlparse(os.environ["ZOOKEEPER_URI"]) (host, port) = (parse.hostname, parse.port) fixture = ExternalService(host, port) else: (host, port) = ("127.0.0.1", None) fixture = cls(host, port) fixture.open() return fixture def __init__(self, host, port, tmp_dir=None): super(ZookeeperFixture, self).__init__() self.host = host self.port = port self.tmp_dir = tmp_dir def kafka_run_class_env(self): env = super(ZookeeperFixture, self).kafka_run_class_env() env['LOG_DIR'] = self.tmp_dir.join('logs').strpath return env def out(self, message): log.info("*** Zookeeper [%s:%s]: %s", self.host, self.port or '(auto)', message) def open(self): if self.tmp_dir is None: self.tmp_dir = py.path.local.mkdtemp() #pylint: disable=no-member self.tmp_dir.ensure(dir=True) self.out("Running local instance...") log.info(" host = %s", self.host) log.info(" port = %s", self.port or '(auto)') log.info(" tmp_dir = %s", self.tmp_dir.strpath) # Configure Zookeeper child process template = self.test_resource("zookeeper.properties") properties = self.tmp_dir.join("zookeeper.properties") args = self.kafka_run_class_args("org.apache.zookeeper.server.quorum.QuorumPeerMain", properties.strpath) env = self.kafka_run_class_env() # Party! timeout = 5 max_timeout = 120 backoff = 1 end_at = time.time() + max_timeout tries = 1 auto_port = (self.port is None) while time.time() < end_at: if auto_port: self.port = get_open_port() self.out('Attempting to start on port %d (try #%d)' % (self.port, tries)) self.render_template(template, properties, vars(self)) self.child = SpawnedService(args, env) self.child.start() timeout = min(timeout, max(end_at - time.time(), 0)) if self.child.wait_for(r"binding to port", timeout=timeout): break self.child.dump_logs() self.child.stop() timeout *= 2 time.sleep(backoff) tries += 1 backoff += 1 else: raise RuntimeError('Failed to start Zookeeper before max_timeout') self.out("Done!") atexit.register(self.close) def close(self): if self.child is None: return self.out("Stopping...") self.child.stop() self.child = None self.out("Done!") self.tmp_dir.remove() def __del__(self): self.close()