Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose OnDeployExecutor Interface and store exception message on result node #1967

Merged
merged 11 commits into from
Jun 29, 2019
Merged
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com)
## Unreleased

### Added
- 1927 - HTTP cache: added cookie exclusion
- 1905 - HTTP cache: added response header exclusion
- #1967 - Expose On-Deploy Script Executor for external script triggering
- #1967 - Write On-Deploy Script exception statement to the result node
- #1927 - HTTP cache: added cookie exclusion
- #1905 - HTTP cache: added response header exclusion

### Changed
- #1945 - Added support for jcr:content creation and update to the Data Importer
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* #%L
* ACS AEM Commons Bundle
* %%
* Copyright (C) 2016 Adobe
* %%
* 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%
*/
package com.adobe.acs.commons.ondeploy;
HitmanInWis marked this conversation as resolved.
Show resolved Hide resolved

/**
* OnDeploy Provider to execute scripts.
*/
public interface OnDeployExecutor {

/**
* Execute scripts
*
* @param scriptName className of the script
* @param force true to run if the script ran already.
* @return true if executed, false if failed.
*/
boolean executeScript(String scriptName, boolean force);

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import java.util.List;

/**
* Provider interface to supply a list of scripts to be run by the OnDeployExecutor.
* Provider interface to supply a list of scripts to be run by the OnDeployExecutorMBean.
*/
@ConsumerType
public interface OnDeployScriptProvider {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
*/
package com.adobe.acs.commons.ondeploy.impl;

import com.adobe.acs.commons.ondeploy.OnDeployExecutor;
import com.adobe.acs.commons.ondeploy.OnDeployScriptProvider;
import com.adobe.acs.commons.ondeploy.scripts.OnDeployScript;
import com.adobe.granite.jmx.annotation.AnnotatedStandardMBean;
import com.day.cq.commons.jcr.JcrConstants;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.felix.scr.annotations.Properties;
Expand Down Expand Up @@ -50,12 +52,12 @@
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Date;
import java.util.Calendar;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

Expand All @@ -80,12 +82,13 @@
metatype = false, policy = ConfigurationPolicy.REQUIRE)
@Properties({ @Property(label = "MBean Name", name = "jmx.objectname",
value = "com.adobe.acs.commons:type=On-Deploy Scripts", propertyPrivate = true) })
@Service(value = DynamicMBean.class)
public class OnDeployExecutorImpl extends AnnotatedStandardMBean implements OnDeployExecutor {
@Service(value = {DynamicMBean.class, OnDeployExecutorMBean.class, OnDeployExecutor.class})
public class OnDeployExecutorImpl extends AnnotatedStandardMBean implements OnDeployExecutorMBean, OnDeployExecutor {
static final String SCRIPT_STATUS_JCR_FOLDER = "/var/acs-commons/on-deploy-scripts-status";

private static final String SCRIPT_DATE_END = "endDate";
private static final String SCRIPT_DATE_START = "startDate";
private static final String SCRIPT_OUTPUT = "output";
private static final String SCRIPT_STATUS = "status";
private static final String SCRIPT_STATUS_FAIL = "fail";
private static final String SCRIPT_STATUS_RUNNING = "running";
Expand Down Expand Up @@ -123,7 +126,7 @@ public class OnDeployExecutorImpl extends AnnotatedStandardMBean implements OnDe
}

public OnDeployExecutorImpl() throws NotCompliantMBeanException {
super(OnDeployExecutor.class);
super(OnDeployExecutorMBean.class);
}

protected void bindResourceResolverFactory(ResourceResolverFactory resourceResolverFactory) {
Expand Down Expand Up @@ -197,12 +200,12 @@ protected boolean runScript(ResourceResolver resourceResolver, OnDeployScript sc
try {
script.execute(resourceResolver);
logger.info("On-deploy script completed successfully: {}", statusResource.getPath());
trackScriptEnd(statusResource, SCRIPT_STATUS_SUCCESS);
trackScriptEnd(statusResource, SCRIPT_STATUS_SUCCESS, "");
return true;
} catch (Exception e) {
String errMsg = "On-deploy script failed: " + statusResource.getPath();
logger.error(errMsg, e);
trackScriptEnd(statusResource, SCRIPT_STATUS_FAIL);
trackScriptEnd(statusResource, SCRIPT_STATUS_FAIL, ExceptionUtils.getStackTrace(e.getCause()));
throw new OnDeployEarlyTerminationException(new RuntimeException(errMsg));
}
} else if (!status.equals(SCRIPT_STATUS_SUCCESS)) {
Expand All @@ -226,11 +229,12 @@ protected void runScripts(ResourceResolver resourceResolver, List<OnDeployScript
}
}

protected void trackScriptEnd(Resource statusResource, String status) {
protected void trackScriptEnd(Resource statusResource, String status, String output) {
try {
ModifiableValueMap properties = statusResource.adaptTo(ModifiableValueMap.class);
properties.put(SCRIPT_STATUS, status);
properties.put(SCRIPT_DATE_END, Calendar.getInstance());
properties.put(SCRIPT_OUTPUT, output);
statusResource.getResourceResolver().commit();
} catch (PersistenceException e) {
logger.error("On-deploy script status node could not be updated: {} - status: {}", statusResource.getPath(), status);
Expand All @@ -245,6 +249,7 @@ protected void trackScriptStart(Resource statusResource) {
properties.put(SCRIPT_STATUS, SCRIPT_STATUS_RUNNING);
properties.put(SCRIPT_DATE_START, Calendar.getInstance());
properties.remove(SCRIPT_DATE_END);
properties.remove(SCRIPT_OUTPUT);
statusResource.getResourceResolver().commit();
} catch (PersistenceException e) {
logger.error("On-deploy script cannot be run because the system could not write to the script status node: {}", statusResource.getPath());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import com.adobe.granite.jmx.annotation.Name;

@Description("ACS AEM Commons - On Deploy Script Executor MBean")
public interface OnDeployExecutor {
public interface OnDeployExecutorMBean {

@Description("Scripts")
TabularDataSupport getScripts() throws OpenDataException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
/**
* On-Deploy Scripts Framework.
*/
@org.osgi.annotation.versioning.Version("1.0.2")
@org.osgi.annotation.versioning.Version("1.1.0")
package com.adobe.acs.commons.ondeploy;
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import org.apache.sling.api.resource.ResourceResolver;

/**
* An on-deploy script that can be run via the OnDeployExecutor.
* An on-deploy script that can be run via the OnDeployExecutorMBean.
*/
@ConsumerType
public interface OnDeployScript {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
/**
* On-Deploy Scripts Framework.
*/
@org.osgi.annotation.versioning.Version("1.0.1")
@org.osgi.annotation.versioning.Version("1.1.0")
package com.adobe.acs.commons.ondeploy.scripts;
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,10 @@ public void testExecuteRerunsFailedScripts() throws RepositoryException, NotComp
String status1ResourcePath = statusResource.getPath();
assertEquals(OnDeployExecutorImpl.SCRIPT_STATUS_JCR_FOLDER + "/" + OnDeployScriptTestExampleSuccess1.class.getName(), status1ResourcePath);
impl.trackScriptStart(statusResource);
impl.trackScriptEnd(statusResource, "fail");
impl.trackScriptEnd(statusResource, "fail", "error message");
Resource originalStatus1 = resourceResolver.getResource(status1ResourcePath);
assertEquals("fail", originalStatus1.getValueMap().get("status", ""));
assertEquals("error message", originalStatus1.getValueMap().get("output", ""));
LogTester.reset();

// Here's where the real test begins
Expand All @@ -164,6 +165,7 @@ public void testExecuteRerunsFailedScripts() throws RepositoryException, NotComp
Resource status1 = resourceResolver.getResource(status1ResourcePath);
assertNotNull(status1);
assertEquals("success", status1.getValueMap().get("status", ""));
assertEquals("", status1.getValueMap().get("output", ""));

Resource status2 = resourceResolver.getResource("/var/acs-commons/on-deploy-scripts-status/" + OnDeployScriptTestExampleSuccess2.class.getName());
assertNotNull(status2);
Expand Down Expand Up @@ -220,10 +222,12 @@ public void testExecuteSkipsAlreadySucccessfulScripts() throws RepositoryExcepti
Resource status1 = resourceResolver.getResource("/var/acs-commons/on-deploy-scripts-status/" + OnDeployScriptTestExampleSuccess1.class.getName());
assertNotNull(status1);
assertEquals("success", status1.getValueMap().get("status", ""));
assertEquals("", status1.getValueMap().get("output", ""));

Resource status2 = resourceResolver.getResource("/var/acs-commons/on-deploy-scripts-status/" + OnDeployScriptTestExampleSuccess2.class.getName());
assertNotNull(status2);
assertEquals("success", status2.getValueMap().get("status", ""));
assertEquals("", status2.getValueMap().get("output", ""));
}

@Test
Expand Down Expand Up @@ -256,6 +260,7 @@ public void testExecuteTerminatesWhenScriptAlreadyRunning() throws RepositoryExc
Resource status1 = resourceResolver.getResource("/var/acs-commons/on-deploy-scripts-status/" + OnDeployScriptTestExampleSuccess1.class.getName());
assertNotNull(status1);
assertEquals("running", status1.getValueMap().get("status", ""));
assertFalse(status1.getValueMap().containsKey("output"));

Resource status2 = resourceResolver.getResource("/var/acs-commons/on-deploy-scripts-status/" + OnDeployScriptTestExampleSuccess2.class.getName());
assertNull(status2);
Expand Down Expand Up @@ -291,10 +296,12 @@ public void testExecuteTerminatesWhenScriptFails() {
Resource status1 = resourceResolver.getResource("/var/acs-commons/on-deploy-scripts-status/" + OnDeployScriptTestExampleSuccess1.class.getName());
assertNotNull(status1);
assertEquals("success", status1.getValueMap().get("status", ""));
assertEquals("", status1.getValueMap().get("output", ""));

Resource status2 = resourceResolver.getResource("/var/acs-commons/on-deploy-scripts-status/" + OnDeployScriptTestExampleFailExecute.class.getName());
assertNotNull(status2);
assertEquals("fail", status2.getValueMap().get("status", ""));
assertTrue(status2.getValueMap().get("output", "").startsWith("java.lang.RuntimeException: Oops, this script failed"));

Resource status3 = resourceResolver.getResource("/var/acs-commons/on-deploy-scripts-status/" + OnDeployScriptTestExampleSuccess2.class.getName());
assertNull(status3);
Expand Down