/** * 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 org.jboss.loom.actions; import org.jboss.as.cli.batch.BatchedCommand; import org.jboss.dmr.ModelNode; import org.jboss.loom.conf.Configuration; import static org.jboss.loom.conf.Configuration.IfExists.ASK; import static org.jboss.loom.conf.Configuration.IfExists.FAIL; import static org.jboss.loom.conf.Configuration.IfExists.MERGE; import static org.jboss.loom.conf.Configuration.IfExists.OVERWRITE; import static org.jboss.loom.conf.Configuration.IfExists.SKIP; import static org.jboss.loom.conf.Configuration.IfExists.WARN; import org.jboss.loom.ex.ActionException; import org.jboss.loom.ex.MigrationException; import org.jboss.loom.spi.IMigrator; import org.jboss.loom.spi.ann.ActionDescriptor; import org.jboss.loom.spi.ann.Property; import org.jboss.loom.utils.as7.AS7CliUtils; import org.jboss.loom.utils.as7.BatchedCommandWithAction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Ondrej Zizka, ozizka at redhat.com */ @ActionDescriptor( header = "Perform CLI command:", props = { @Property(name="cliCommand", expr = "command.command", style = "code") // TODO } ) public class CliCommandAction extends AbstractStatefulAction { private static final Logger log = LoggerFactory.getLogger(CliCommandAction.class); /** Management API command to perform. */ private BatchedCommandWithAction command; /** What to do if the resource (node) already exists (for ADD operations). */ private Configuration.IfExists ifExists = Configuration.IfExists.WARN; // Workflow control - what to do in the perform step. private Configuration.IfExists todo = null; /** * @param script Text script * @param cliCommand CLI API object, must do the same as text script.. * @deprecated Use either String-only or ModalNode-only constructors - they will convert the other one. */ public CliCommandAction( Class<? extends IMigrator> fromMigrator, String script, ModelNode cliCommand) { super(fromMigrator); this.command = new BatchedCommandWithAction(this, script, cliCommand); } /** * ModelNode is created by paring $script. */ public CliCommandAction( Class<? extends IMigrator> fromMigrator, String script ) { this( fromMigrator, script, AS7CliUtils.parseCommand( script ) ); } /** * Script is created by formatting ModelNode. */ public CliCommandAction( Class<? extends IMigrator> fromMigrator, ModelNode cliCommand ) { this( fromMigrator, AS7CliUtils.formatCommand( cliCommand ), cliCommand ); } @Override public String toDescription() { return "Perform CLI command: " + this.command.getCommand() + " ; ifExists=" + ifExists + ", todo=" + todo; } @Override public void preValidate() throws MigrationException { if ((this.command.getCommand() == null) || (this.command.getCommand().isEmpty())) throw new ActionException(this, "No CLI script set for CliCommandAction."); if (this.command.getRequest() == null) { throw new ActionException(this, "ModelNode for CliCommandAction cannot be null."); } // If already exists, boolean exists; try { exists = AS7CliUtils.exists( this.command.getRequest(), getMigrationContext().getAS7Client() ); //log.debug( "Exists? " + exists + " : " + this.command ); } catch( Exception ex ) { throw new ActionException( this, "Failed querying AS 7 for existence of " + this.command.getRequest() + ": " + ex, ex ); } if( ! exists ) return; // ... act as per configuration. switch( this.ifExists ){ case OVERWRITE: this.todo = OVERWRITE; break; case FAIL: throw new ActionException(this, "ModelNode already exists in AS 7 config: " + this.command.getCommand() ); case MERGE: throw new UnsupportedOperationException("ModelNode merging not supported yet. MIGR-61"); case WARN: this.todo = SKIP; log.warn("ModelNode already exists in AS 7 config: " + this.command.getCommand() ); return; case SKIP: this.todo = SKIP; return; case ASK: throw new UnsupportedOperationException("Interactive duplicity handling not supported yet. MIGR-62"); } }// preValidate() @Override public void perform() throws MigrationException { if( this.todo == SKIP ) return; if( this.todo == OVERWRITE ){ // Remove the pre-existing node. ModelNode remCmd = AS7CliUtils.createRemoveCommandForResource( this.command.getRequest() ); //log.debug("\n Adding REMOVE operation: " + remCmd); String desc = AS7CliUtils.formatCommand( remCmd ); //remCmd.asString(); getMigrationContext().getBatch().add( new BatchedCommandWithAction( this, desc, remCmd) ); } // Perform. getMigrationContext().getBatch().add(this.command); setState(State.DONE); } @Override public void rollback() throws MigrationException { // Batch provides rollback. setState(State.ROLLED_BACK); } @Override public void postValidate() throws MigrationException { // Empty } @Override public void backup() throws MigrationException { // Batch handles backup. setState(State.BACKED_UP); } @Override public void cleanBackup() { // Empty setState(State.FINISHED); } //<editor-fold defaultstate="collapsed" desc="get/set"> public BatchedCommand getCommand() { return command; } public void setCommand( BatchedCommand command ) { this.command = new BatchedCommandWithAction( this, command ); } public Configuration.IfExists getIfExists() { return ifExists; } public CliCommandAction setIfExists( Configuration.IfExists ifExists ) { this.ifExists = ifExists; return this; } //</editor-fold> /* * Workaround until MIGR-128. * TODO: Rename getCommand() to getBatchCommand() and this to getCommand(). */ @Property(name = "cliCommand", style = "code") public String getCommandCommand(){ return this.command.getCommand(); } @Override public String toString() { return "CliCommandAction{" + command.getCommand() + "; ifExists=" + ifExists + ", todo=" + todo + '}'; } }// class