// Copyright 2016 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.google.pubsub.kafka.sink; import com.google.pubsub.kafka.common.ConnectorUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.kafka.common.config.ConfigDef; import org.apache.kafka.common.config.ConfigDef.Importance; import org.apache.kafka.common.config.ConfigDef.Type; import org.apache.kafka.common.utils.AppInfoParser; import org.apache.kafka.connect.connector.Task; import org.apache.kafka.connect.sink.SinkConnector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A {@link SinkConnector} that writes messages to a specified topic in <a * href="https://cloud.google.com/pubsub">Google Cloud Pub/Sub</a>. */ public class CloudPubSubSinkConnector extends SinkConnector { private static final Logger log = LoggerFactory.getLogger(CloudPubSubSinkConnector.class); public static final String MAX_BUFFER_SIZE_CONFIG = "maxBufferSize"; public static final int DEFAULT_MAX_BUFFER_SIZE = 100; public static final String CPS_MESSAGE_BODY_NAME = "messageBodyName"; public static final String DEFAULT_MESSAGE_BODY_NAME = "cps_message_body"; private Map<String, String> props; @Override public String version() { return AppInfoParser.getVersion(); } @Override public void start(Map<String, String> props) { this.props = props; log.info("Started the CloudPubSubSinkConnector."); } @Override public Class<? extends Task> taskClass() { return CloudPubSubSinkTask.class; } @Override public List<Map<String, String>> taskConfigs(int maxTasks) { // Each task will get the exact same configuration. Delegate all config validation to the task. ArrayList<Map<String, String>> configs = new ArrayList<>(); for (int i = 0; i < maxTasks; i++) { Map<String, String> config = new HashMap<>(props); configs.add(config); } return configs; } @Override public ConfigDef config() { return new ConfigDef() .define( ConnectorUtils.CPS_PROJECT_CONFIG, Type.STRING, Importance.HIGH, "The project containing the topic to which to publish.") .define( ConnectorUtils.CPS_TOPIC_CONFIG, Type.STRING, Importance.HIGH, "The topic to which to publish.") .define( MAX_BUFFER_SIZE_CONFIG, Type.INT, DEFAULT_MAX_BUFFER_SIZE, ConfigDef.Range.between(1, Integer.MAX_VALUE), Importance.MEDIUM, "The maximum number of messages that can be received for the messages on a topic " + "partition before publishing them to Cloud Pub/Sub.") .define(CPS_MESSAGE_BODY_NAME, Type.STRING, DEFAULT_MESSAGE_BODY_NAME, Importance.MEDIUM, "When using a struct or map value schema, this field or key name indicates that the " + "corresponding value will go into the Pub/Sub message body."); } @Override public void stop() {} }