diff --git a/client/src/main/java/org/apache/sqoop/client/shell/CloneCommand.java b/client/src/main/java/org/apache/sqoop/client/shell/CloneCommand.java new file mode 100644 index 00000000..847a6ad7 --- /dev/null +++ b/client/src/main/java/org/apache/sqoop/client/shell/CloneCommand.java @@ -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); + } + } +} diff --git a/client/src/main/java/org/apache/sqoop/client/shell/CloneConnectionFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/CloneConnectionFunction.java new file mode 100644 index 00000000..9716de6e --- /dev/null +++ b/client/src/main/java/org/apache/sqoop/client/shell/CloneConnectionFunction.java @@ -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 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); + } +} diff --git a/client/src/main/java/org/apache/sqoop/client/shell/CloneJobFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/CloneJobFunction.java new file mode 100644 index 00000000..6c579d09 --- /dev/null +++ b/client/src/main/java/org/apache/sqoop/client/shell/CloneJobFunction.java @@ -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 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); + } +} diff --git a/client/src/main/java/org/apache/sqoop/client/shell/SqoopShell.java b/client/src/main/java/org/apache/sqoop/client/shell/SqoopShell.java index 91682d1d..ee38407d 100644 --- a/client/src/main/java/org/apache/sqoop/client/shell/SqoopShell.java +++ b/client/src/main/java/org/apache/sqoop/client/shell/SqoopShell.java @@ -63,6 +63,7 @@ public static void main (String[] args) throws Exception shell.register(new CreateCommand(shell)); shell.register(new DeleteCommand(shell)); shell.register(new UpdateCommand(shell)); + shell.register(new CloneCommand(shell)); if (args.length == 0) { // Interactive mode: diff --git a/client/src/main/java/org/apache/sqoop/client/shell/UpdateJobFunction.java b/client/src/main/java/org/apache/sqoop/client/shell/UpdateJobFunction.java index 58749e97..9924cf9a 100644 --- a/client/src/main/java/org/apache/sqoop/client/shell/UpdateJobFunction.java +++ b/client/src/main/java/org/apache/sqoop/client/shell/UpdateJobFunction.java @@ -33,7 +33,7 @@ import java.util.List; import java.util.ResourceBundle; -import static org.apache.sqoop.client.utils.FormFiller.fillForms; +import static org.apache.sqoop.client.utils.FormFiller.*; /** *