001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 020package org.apache.oozie.action.hadoop; 021 022import java.io.File; 023import java.util.List; 024import java.util.Map; 025 026import org.apache.hadoop.conf.Configuration; 027import org.apache.hadoop.fs.Path; 028import org.apache.hadoop.yarn.util.Apps; 029import org.apache.oozie.action.ActionExecutorException; 030import org.apache.oozie.service.ConfigurationService; 031import org.jdom.Element; 032import org.jdom.Namespace; 033 034public class ShellActionExecutor extends JavaActionExecutor { 035 036 public ShellActionExecutor() { 037 super("shell"); 038 } 039 040 @Override 041 public List<Class<?>> getLauncherClasses() { 042 return null; 043 } 044 045 @Override 046 protected String getLauncherMain(Configuration launcherConf, Element actionXml) { 047 return launcherConf.get(LauncherAMUtils.CONF_OOZIE_ACTION_MAIN_CLASS, ShellMain.class.getName()); 048 } 049 050 @Override 051 Configuration setupActionConf(Configuration actionConf, Context context, Element actionXml, Path appPath) 052 throws ActionExecutorException { 053 super.setupActionConf(actionConf, context, actionXml, appPath); 054 Namespace ns = actionXml.getNamespace(); 055 056 String exec = actionXml.getChild("exec", ns).getTextTrim(); 057 String execName = new Path(exec).getName(); 058 actionConf.set(ShellMain.CONF_OOZIE_SHELL_EXEC, execName); 059 060 // Setting Shell command's arguments 061 setListInConf("argument", actionXml, actionConf, ShellMain.CONF_OOZIE_SHELL_ARGS, false); 062 // Setting Shell command's environment variable key=value 063 setListInConf("env-var", actionXml, actionConf, ShellMain.CONF_OOZIE_SHELL_ENVS, true); 064 065 // Setting capture output flag 066 actionConf.setBoolean(ShellMain.CONF_OOZIE_SHELL_CAPTURE_OUTPUT, actionXml.getChild("capture-output", ns) != null); 067 068 // Setting if ShellMain should setup HADOOP_CONF_DIR 069 boolean setupHadoopConfDir = actionConf.getBoolean(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR, 070 ConfigurationService.getBoolean(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR)); 071 actionConf.setBoolean(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR, setupHadoopConfDir); 072 // Setting to control if ShellMain should write log4j.properties 073 boolean writeL4J = actionConf.getBoolean(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR_WRITE_LOG4J_PROPERTIES, 074 ConfigurationService.getBoolean(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR_WRITE_LOG4J_PROPERTIES)); 075 actionConf.setBoolean(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR_WRITE_LOG4J_PROPERTIES, writeL4J); 076 // Setting of content of log4j.properties, if to be written 077 if (writeL4J) { 078 String l4jContent = actionConf.get(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR_LOG4J_CONTENT, 079 ConfigurationService.get(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR_LOG4J_CONTENT)); 080 actionConf.set(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR_LOG4J_CONTENT, l4jContent); 081 } 082 083 return actionConf; 084 } 085 086 /** 087 * This method read a list of tag from an XML element and set the 088 * Configuration accordingly 089 * 090 * @param tag 091 * @param actionXml 092 * @param actionConf 093 * @param key 094 * @param checkKeyValue 095 * @throws ActionExecutorException 096 */ 097 protected void setListInConf(String tag, Element actionXml, Configuration actionConf, String key, 098 boolean checkKeyValue) throws ActionExecutorException { 099 String[] strTagValue = null; 100 Namespace ns = actionXml.getNamespace(); 101 @SuppressWarnings("unchecked") 102 List<Element> eTags = actionXml.getChildren(tag, ns); 103 if (eTags != null && eTags.size() > 0) { 104 strTagValue = new String[eTags.size()]; 105 for (int i = 0; i < eTags.size(); i++) { 106 strTagValue[i] = eTags.get(i).getTextTrim(); 107 if (checkKeyValue) { 108 checkPair(strTagValue[i]); 109 } 110 } 111 } 112 ActionUtils.setStrings(actionConf, key, strTagValue); 113 } 114 115 /** 116 * Check if the key=value pair is appropriately formatted 117 * @param pair 118 * @throws ActionExecutorException 119 */ 120 private void checkPair(String pair) throws ActionExecutorException { 121 String[] varValue = pair.split("="); 122 if (varValue == null || varValue.length <= 1) { 123 throw new ActionExecutorException(ActionExecutorException.ErrorType.FAILED, "JA010", 124 "Wrong ENV format [{0}] in <env-var> , key=value format expected ", pair); 125 } 126 } 127 128 @Override 129 protected void addActionSpecificEnvVars(Map<String, String> env) { 130 Apps.setEnvFromInputString(env, "PATH=.:$PATH", File.pathSeparator); 131 } 132 133 /** 134 * Utility method to append the new value to any property. 135 * 136 * @param conf 137 * @param propertyName 138 * @param appendValue 139 */ 140 private void updateProperty(Configuration conf, String propertyName, String appendValue) { 141 if (conf != null) { 142 String val = conf.get(propertyName, ""); 143 if (val.length() > 0) { 144 val += ","; 145 } 146 val += appendValue; 147 conf.set(propertyName, val); 148 LOG.debug("action conf is updated with default value for property " + propertyName + ", old value :" 149 + conf.get(propertyName, "") + ", new value :" + val); 150 } 151 } 152 153}