package com.thinkbiganalytics.nifi.v2.sqoop; /*- * #%L * thinkbig-nifi-hadoop-service * %% * Copyright (C) 2017 ThinkBig Analytics * %% * 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. * #L% */ import org.apache.nifi.annotation.lifecycle.OnEnabled; import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.controller.AbstractControllerService; import org.apache.nifi.controller.ConfigurationContext; import org.apache.nifi.processor.util.StandardValidators; import org.apache.nifi.reporting.InitializationException; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * An implementation for {@link SqoopConnectionService} to provide connection details to a relational system for running a sqoop job */ public class StandardSqoopConnectionService extends AbstractControllerService implements SqoopConnectionService { /** * A property to provide the connection string for accessing the relational source system. */ public static final PropertyDescriptor SOURCE_CONNECTION_STRING = new PropertyDescriptor.Builder() .name("Source Connection String") .description("The connection string for accessing the relational source system. " + "Sqoop will attempt to determine the best connector and driver based upon this value. " + "In most cases, this behavior should be OK and acceptable. " + "[*** Note 1: If you need to manually specify a connector, provide it via the (optional) Source Connection Manager property.] " + "[*** Note 2: Based upon the connector, Sqoop will automatically choose a best Source Driver. " + "In the rare case that you need to manually specify a driver, provide it via the (optional) Source Driver property. " + "Please be careful: If a driver is manually provided, the Generic JDBC Connector will always be used and any other optimized connectors will be ignored, even if available. " + " *---> So, in most cases, you should not need to provide a Source Driver value <---*]") .required(true) .expressionLanguageSupported(true) .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) .build(); /** * A property to get the user name for accessing the relational source system */ public static final PropertyDescriptor SOURCE_USERNAME = new PropertyDescriptor.Builder() .name("Source User Name") .description("The user name for accessing the relational source system") .required(true) .expressionLanguageSupported(true) .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) .build(); /** * A property to get the password mode, which indicates type of password and how it is provided. */ public static final PropertyDescriptor PASSWORD_MODE = new PropertyDescriptor.Builder() .name("Password Mode") .description("Indicates type of password and how it is provided. " + "(1) Entered as clear text (2) Entered as encrypted text (3) Location of file on HDFS containing encrypted password") .required(true) .expressionLanguageSupported(false) .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) .allowableValues(PasswordMode.values()) .defaultValue(PasswordMode.ENCRYPTED_ON_HDFS_FILE.toString()) .build(); /** * A property to get the HDFS location containing encrypted password file for accessing the relational source system. */ public static final PropertyDescriptor SOURCE_PASSWORD_HDFS_FILE = new PropertyDescriptor.Builder() .name("Source Password File") .description("The HDFS location containing encrypted password file for accessing the relational source system.") .required(false) .expressionLanguageSupported(true) .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) .sensitive(true) .build(); /** * A property to get the passphrase to decrypt the password for connecting to source system. */ public static final PropertyDescriptor SOURCE_PASSWORD_PASSPHRASE = new PropertyDescriptor.Builder() .name("Source Password Passphrase") .description("The passphrase to decrypt the password for connecting to source system.") .required(false) .expressionLanguageSupported(true) .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) .sensitive(true) .build(); /** * A property to get the password (can be either encrypted or clear text). */ public static final PropertyDescriptor SOURCE_ENTERED_PASSWORD = new PropertyDescriptor.Builder() .name("Source Password (Encrypted Base64/Clear Text)") .description("The password (can be either encrypted or clear text). " + "For encrypted password, use the base64 encoded version which is output by the encryption utility. " + "The Password Mode indicates how the password will be obtained and/or decrypted.") .required(false) .expressionLanguageSupported(true) .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) .sensitive(true) .build(); /** * A property to get the connection manager (also called connector) to use for accessing the relational source system. */ public static final PropertyDescriptor SOURCE_CONNECTION_MANAGER = new PropertyDescriptor.Builder() .name("Source Connection Manager") .description("The connection manager (also called connector) to use for accessing the relational source system. " + "Note: Sqoop will try to detect the best connection manager automatically. So, providing this value is optional, and may even be not recommended in some cases. " + "See description of Source Connection String property for full explanation.") .required(false) .expressionLanguageSupported(true) .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) .build(); /** * A property to get the driver for accessing the relational source system. */ public static final PropertyDescriptor SOURCE_DRIVER = new PropertyDescriptor.Builder() .name("Source Driver (Avoid providing value)") .description("The driver for accessing the relational source system. " + "Note: This should be auto-detected. Try to avoid providing a value for this property. See description of Source Connection String property for full explanation.") .required(false) .expressionLanguageSupported(true) .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) .build(); private static final List<PropertyDescriptor> sqoopConnectionProperties; static { final List<PropertyDescriptor> properties = new ArrayList<>(); properties.add(SOURCE_CONNECTION_STRING); properties.add(SOURCE_USERNAME); properties.add(PASSWORD_MODE); properties.add(SOURCE_PASSWORD_HDFS_FILE); properties.add(SOURCE_PASSWORD_PASSPHRASE); properties.add(SOURCE_ENTERED_PASSWORD); properties.add(SOURCE_CONNECTION_MANAGER); properties.add(SOURCE_DRIVER); sqoopConnectionProperties = Collections.unmodifiableList(properties); } private String sourceConnectionString; private String sourceUserName; private PasswordMode passwordMode; private String sourcePasswordHdfsFile; private String sourcePasswordPassphrase; private String sourceEnteredPassword; private String sourceConnectionManager; private String sourceDriver; @Override protected List<PropertyDescriptor> getSupportedPropertyDescriptors() { return sqoopConnectionProperties; } /** * Called when the controller service is initiated. It will set up access to the various properties. * * @param context the configuration context gives access to properties * @throws InitializationException if there are any issues accessing the properties */ @OnEnabled public void onConfigured(final ConfigurationContext context) throws InitializationException { sourceConnectionString = context.getProperty(SOURCE_CONNECTION_STRING).evaluateAttributeExpressions().getValue(); sourceUserName = context.getProperty(SOURCE_USERNAME).evaluateAttributeExpressions().getValue(); passwordMode = PasswordMode.valueOf(context.getProperty(PASSWORD_MODE).getValue()); sourcePasswordHdfsFile = context.getProperty(SOURCE_PASSWORD_HDFS_FILE).evaluateAttributeExpressions().getValue(); sourcePasswordPassphrase = context.getProperty(SOURCE_PASSWORD_PASSPHRASE).evaluateAttributeExpressions().getValue(); sourceEnteredPassword = context.getProperty(SOURCE_ENTERED_PASSWORD).evaluateAttributeExpressions().getValue(); sourceConnectionManager = context.getProperty(SOURCE_CONNECTION_MANAGER).evaluateAttributeExpressions().getValue(); sourceDriver = context.getProperty(SOURCE_DRIVER).evaluateAttributeExpressions().getValue(); } @Override public String getConnectionString() { return this.sourceConnectionString; } @Override public String getUserName() { return this.sourceUserName; } @Override public PasswordMode getPasswordMode() { return this.passwordMode; } @Override public String getPasswordHdfsFile() { return this.sourcePasswordHdfsFile; } @Override public String getPasswordPassphrase() { return this.sourcePasswordPassphrase; } @Override public String getEnteredPassword() { return this.sourceEnteredPassword; } @Override public String getConnectionManager() { return this.sourceConnectionManager; } @Override public String getDriver() { return this.sourceDriver; } }