mirror of
https://github.com/apache/sqoop.git
synced 2025-05-07 17:41:05 +08:00
SQOOP-614 Provide client side ability to clone connection or job object
This commit is contained in:
parent
13439909f3
commit
31d6f72761
@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.sqoop.client.shell;
|
||||||
|
|
||||||
|
import org.apache.sqoop.client.core.ClientError;
|
||||||
|
import org.apache.sqoop.common.SqoopException;
|
||||||
|
import org.codehaus.groovy.tools.shell.Shell;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client side cloning of connection and job objects.
|
||||||
|
*/
|
||||||
|
public class CloneCommand extends SqoopCommand {
|
||||||
|
|
||||||
|
private CloneConnectionFunction connectionFunction;
|
||||||
|
private CloneJobFunction jobFunction;
|
||||||
|
|
||||||
|
public CloneCommand(Shell shell) {
|
||||||
|
super(shell, "clone", "\\cl",
|
||||||
|
new String[] {"connection", "job"},
|
||||||
|
"Clone", "Info");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object execute(List args) {
|
||||||
|
if (args.size() == 0) {
|
||||||
|
io.out.println("Usage: clone " + getUsage());
|
||||||
|
io.out.println();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String func = (String)args.get(0);
|
||||||
|
if (func.equals("connection")) {
|
||||||
|
if (connectionFunction == null) {
|
||||||
|
connectionFunction = new CloneConnectionFunction(io);
|
||||||
|
}
|
||||||
|
return connectionFunction.execute(args);
|
||||||
|
} else if (func.equals("job")) {
|
||||||
|
if (jobFunction == null) {
|
||||||
|
jobFunction = new CloneJobFunction(io);
|
||||||
|
}
|
||||||
|
return jobFunction.execute(args);
|
||||||
|
} else {
|
||||||
|
String msg = "Usage: clone " + getUsage();
|
||||||
|
throw new SqoopException(ClientError.CLIENT_0002, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,141 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.sqoop.client.shell;
|
||||||
|
|
||||||
|
import jline.ConsoleReader;
|
||||||
|
import org.apache.commons.cli.CommandLine;
|
||||||
|
import org.apache.commons.cli.OptionBuilder;
|
||||||
|
import org.apache.sqoop.client.core.ClientError;
|
||||||
|
import org.apache.sqoop.client.core.Environment;
|
||||||
|
import org.apache.sqoop.client.request.ConnectionRequest;
|
||||||
|
import org.apache.sqoop.common.SqoopException;
|
||||||
|
import org.apache.sqoop.json.ConnectionBean;
|
||||||
|
import org.apache.sqoop.model.MConnection;
|
||||||
|
import org.apache.sqoop.model.MPersistableEntity;
|
||||||
|
import org.apache.sqoop.validation.Status;
|
||||||
|
import org.codehaus.groovy.tools.shell.IO;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
import static org.apache.sqoop.client.utils.FormFiller.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CloneConnectionFunction extends SqoopFunction {
|
||||||
|
|
||||||
|
private static final String XID = "xid";
|
||||||
|
|
||||||
|
private ConnectionRequest connectionRequest;
|
||||||
|
|
||||||
|
private IO io;
|
||||||
|
|
||||||
|
@SuppressWarnings("static-access")
|
||||||
|
public CloneConnectionFunction(IO io) {
|
||||||
|
this.io = io;
|
||||||
|
|
||||||
|
this.addOption(OptionBuilder
|
||||||
|
.withDescription("Connection ID")
|
||||||
|
.withLongOpt(XID)
|
||||||
|
.hasArg()
|
||||||
|
.create(XID.charAt(0))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object execute(List<String> args) {
|
||||||
|
CommandLine line = parseOptions(this, 1, args);
|
||||||
|
if (!line.hasOption(XID)) {
|
||||||
|
io.out.println("Required argument --xid is missing.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
cloneConnection(line.getOptionValue(XID));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new SqoopException(ClientError.CLIENT_0005, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cloneConnection(String connectionId) throws IOException {
|
||||||
|
io.out.println("Cloning connection with id " + connectionId);
|
||||||
|
|
||||||
|
ConsoleReader reader = new ConsoleReader();
|
||||||
|
|
||||||
|
ConnectionBean connectionBean = readConnection(connectionId);
|
||||||
|
|
||||||
|
// TODO(jarcec): Check that we have expected data
|
||||||
|
MConnection connection = connectionBean.getConnections().get(0);
|
||||||
|
ResourceBundle frameworkBundle
|
||||||
|
= connectionBean.getFrameworkBundle();
|
||||||
|
ResourceBundle connectorBundle
|
||||||
|
= connectionBean.getConnectorBundle(connection.getConnectorId());
|
||||||
|
|
||||||
|
// Remove persistent id as we're making a clone
|
||||||
|
connection.setPersistenceId(MPersistableEntity.PERSISTANCE_ID_DEFAULT);
|
||||||
|
|
||||||
|
Status status = Status.FINE;
|
||||||
|
|
||||||
|
io.out.println("Please update connection metadata:");
|
||||||
|
|
||||||
|
do {
|
||||||
|
if( !status.canProceed() ) {
|
||||||
|
io.out.println();
|
||||||
|
io.out.println("@|red There are issues with entered data, please"
|
||||||
|
+ " revise your input:|@");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query connector forms
|
||||||
|
if(!fillForms(io, connection.getConnectorPart().getForms(),
|
||||||
|
reader, connectorBundle)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query framework forms
|
||||||
|
if(!fillForms(io, connection.getFrameworkPart().getForms(),
|
||||||
|
reader, frameworkBundle)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to create
|
||||||
|
status = createConnection(connection);
|
||||||
|
} while(!status.canProceed());
|
||||||
|
|
||||||
|
io.out.println("Connection was successfully updated with status "
|
||||||
|
+ status.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Status createConnection(MConnection connection) {
|
||||||
|
if (connectionRequest == null) {
|
||||||
|
connectionRequest = new ConnectionRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
return connectionRequest.create(Environment.getServerUrl(), connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConnectionBean readConnection(String connectionId) {
|
||||||
|
if (connectionRequest == null) {
|
||||||
|
connectionRequest = new ConnectionRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
return connectionRequest.read(Environment.getServerUrl(), connectionId);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,140 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.sqoop.client.shell;
|
||||||
|
|
||||||
|
import jline.ConsoleReader;
|
||||||
|
import org.apache.commons.cli.CommandLine;
|
||||||
|
import org.apache.commons.cli.OptionBuilder;
|
||||||
|
import org.apache.sqoop.client.core.ClientError;
|
||||||
|
import org.apache.sqoop.client.core.Environment;
|
||||||
|
import org.apache.sqoop.client.request.JobRequest;
|
||||||
|
import org.apache.sqoop.common.SqoopException;
|
||||||
|
import org.apache.sqoop.json.JobBean;
|
||||||
|
import org.apache.sqoop.model.MJob;
|
||||||
|
import org.apache.sqoop.model.MPersistableEntity;
|
||||||
|
import org.apache.sqoop.validation.Status;
|
||||||
|
import org.codehaus.groovy.tools.shell.IO;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
import static org.apache.sqoop.client.utils.FormFiller.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CloneJobFunction extends SqoopFunction {
|
||||||
|
|
||||||
|
private static final String JID = "jid";
|
||||||
|
|
||||||
|
private JobRequest jobRequest;
|
||||||
|
|
||||||
|
private IO io;
|
||||||
|
|
||||||
|
@SuppressWarnings("static-access")
|
||||||
|
public CloneJobFunction(IO io) {
|
||||||
|
this.io = io;
|
||||||
|
|
||||||
|
this.addOption(OptionBuilder
|
||||||
|
.withDescription("Job ID")
|
||||||
|
.withLongOpt(JID)
|
||||||
|
.hasArg()
|
||||||
|
.create(JID.charAt(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object execute(List<String> args) {
|
||||||
|
CommandLine line = parseOptions(this, 1, args);
|
||||||
|
if (!line.hasOption(JID)) {
|
||||||
|
io.out.println("Required argument --jid is missing.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
cloneJob(line.getOptionValue(JID));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new SqoopException(ClientError.CLIENT_0005, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cloneJob(String jobId) throws IOException {
|
||||||
|
io.out.println("Cloning job with id " + jobId);
|
||||||
|
|
||||||
|
ConsoleReader reader = new ConsoleReader();
|
||||||
|
|
||||||
|
JobBean jobBean = readJob(jobId);
|
||||||
|
|
||||||
|
// TODO(jarcec): Check that we have expected data
|
||||||
|
MJob job = jobBean.getJobs().get(0);
|
||||||
|
ResourceBundle frameworkBundle
|
||||||
|
= jobBean.getFrameworkBundle();
|
||||||
|
ResourceBundle connectorBundle
|
||||||
|
= jobBean.getConnectorBundle(job.getConnectorId());
|
||||||
|
|
||||||
|
Status status = Status.FINE;
|
||||||
|
|
||||||
|
// Remove persistent id as we're making a clone
|
||||||
|
job.setPersistenceId(MPersistableEntity.PERSISTANCE_ID_DEFAULT);
|
||||||
|
|
||||||
|
io.out.println("Please update job metadata:");
|
||||||
|
|
||||||
|
do {
|
||||||
|
if( !status.canProceed() ) {
|
||||||
|
io.out.println();
|
||||||
|
io.out.println("@|red There are issues with entered data, please"
|
||||||
|
+ " revise your input:|@");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query connector forms
|
||||||
|
if(!fillForms(io, job.getConnectorPart().getForms(),
|
||||||
|
reader, connectorBundle)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query framework forms
|
||||||
|
if(!fillForms(io, job.getFrameworkPart().getForms(),
|
||||||
|
reader, frameworkBundle)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to create
|
||||||
|
status = createJob(job);
|
||||||
|
} while(!status.canProceed());
|
||||||
|
|
||||||
|
io.out.println("Job was successfully updated with status "
|
||||||
|
+ status.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Status createJob(MJob job) {
|
||||||
|
if (jobRequest == null) {
|
||||||
|
jobRequest = new JobRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
return jobRequest.create(Environment.getServerUrl(), job);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JobBean readJob(String jobId) {
|
||||||
|
if (jobRequest == null) {
|
||||||
|
jobRequest = new JobRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
return jobRequest.read(Environment.getServerUrl(), jobId);
|
||||||
|
}
|
||||||
|
}
|
@ -63,6 +63,7 @@ public static void main (String[] args) throws Exception
|
|||||||
shell.register(new CreateCommand(shell));
|
shell.register(new CreateCommand(shell));
|
||||||
shell.register(new DeleteCommand(shell));
|
shell.register(new DeleteCommand(shell));
|
||||||
shell.register(new UpdateCommand(shell));
|
shell.register(new UpdateCommand(shell));
|
||||||
|
shell.register(new CloneCommand(shell));
|
||||||
|
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
// Interactive mode:
|
// Interactive mode:
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
import static org.apache.sqoop.client.utils.FormFiller.fillForms;
|
import static org.apache.sqoop.client.utils.FormFiller.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user