This is an automated email from the ASF dual-hosted git repository.
jonathanhurley pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/trunk by this push:
new cd39737 [AMBARI-24812] - Implement New Upgrade Check Which Warns
About Missing Plugin Checks (#2497)
cd39737 is described below
commit cd397373e6d7a0d976ee50e61466cfe184cfb6a7
Author: Jonathan Hurley <[email protected]>
AuthorDate: Tue Oct 23 14:22:01 2018 -0400
[AMBARI-24812] - Implement New Upgrade Check Which Warns About Missing
Plugin Checks (#2497)
---
.../server/checks/PluginChecksLoadedCheck.java | 172 +++++++++++++++++++++
.../ambari/server/checks/UpgradeCheckRegistry.java | 68 +++++++-
.../server/checks/PluginChecksLoadedCheckTest.java | 101 ++++++++++++
.../PreUpgradeCheckResourceProviderTest.java | 2 +-
4 files changed, 335 insertions(+), 8 deletions(-)
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/checks/PluginChecksLoadedCheck.java
b/ambari-server/src/main/java/org/apache/ambari/server/checks/PluginChecksLoadedCheck.java
new file mode 100644
index 0000000..5538919
--- /dev/null
+++
b/ambari-server/src/main/java/org/apache/ambari/server/checks/PluginChecksLoadedCheck.java
@@ -0,0 +1,172 @@
+/*
+ * 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.ambari.server.checks;
+
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.ambari.annotations.UpgradeCheckInfo;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.spi.upgrade.UpgradeCheckDescription;
+import org.apache.ambari.spi.upgrade.UpgradeCheckGroup;
+import org.apache.ambari.spi.upgrade.UpgradeCheckRequest;
+import org.apache.ambari.spi.upgrade.UpgradeCheckResult;
+import org.apache.ambari.spi.upgrade.UpgradeCheckStatus;
+import org.apache.ambari.spi.upgrade.UpgradeCheckType;
+import org.apache.ambari.spi.upgrade.UpgradeType;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+/**
+ * The {@link PluginChecksLoadedCheck} class is used to display warnings if
+ * there were any stack plugin checks which were not able to be loaded.
+ */
+@Singleton
+@UpgradeCheckInfo(
+ group = UpgradeCheckGroup.INFORMATIONAL_WARNING,
+ required = { UpgradeType.ROLLING, UpgradeType.NON_ROLLING,
UpgradeType.HOST_ORDERED })
+public class PluginChecksLoadedCheck extends ClusterCheck {
+
+ private static final UpgradeCheckDescription PLUGIN_CHECK_LOAD_FAILURE = new
UpgradeCheckDescription(
+ "PLUGIN_CHECK_LOAD_FAILURE", UpgradeCheckType.CLUSTER, "Plugin Upgrade
Checks",
+ new ImmutableMap.Builder<String,
String>().put(UpgradeCheckDescription.DEFAULT,
+ "The following upgrade checks could not be loaded and were not run. "
+ + "Although this will not prevent your ability to upgrade, it is
advised that you "
+ + "correct these checks before proceeding.").build());
+
+ @Inject
+ Provider<UpgradeCheckRegistry> m_upgradeCheckRegistryProvider;
+
+ /**
+ * Constructor.
+ */
+ public PluginChecksLoadedCheck() {
+ super(PLUGIN_CHECK_LOAD_FAILURE);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public UpgradeCheckResult perform(UpgradeCheckRequest request) throws
AmbariException {
+ UpgradeCheckResult result = new UpgradeCheckResult(this,
UpgradeCheckStatus.PASS);
+
+ // get the fully-qualified class names
+ Set<String> failedPluginClasses =
m_upgradeCheckRegistryProvider.get().getFailedPluginClassNames();
+
+ // quick return a pass
+ if (null == failedPluginClasses || failedPluginClasses.isEmpty()) {
+ return result;
+ }
+
+ // strip out the package name for readability
+ Set<FailedPluginClassDetail> failedPluginSimpleClasses =
failedPluginClasses.stream()
+ .map(FailedPluginClassDetail::new)
+ .collect(Collectors.toSet());
+
+ // check for failure
+ if (failedPluginClasses.size() > 0) {
+ result.setStatus(UpgradeCheckStatus.WARNING);
+ result.getFailedDetail().addAll(failedPluginSimpleClasses);
+ result.setFailReason(getFailReason(result, request));
+
+ result.getFailedOn().addAll(failedPluginSimpleClasses.stream()
+ .map(detail -> detail.toSimpleString())
+ .collect(Collectors.toSet()));
+ }
+
+ return result;
+ }
+
+ /**
+ * Used to represent serializable structured information about plugin upgrade
+ * checks which could not load.
+ */
+ static class FailedPluginClassDetail {
+ final String m_fullyQualifiedClass;
+
+ @JsonProperty("package_name")
+ final String m_packageName;
+
+ @JsonProperty("class_name")
+ final String m_className;
+
+ FailedPluginClassDetail(String fullyQualifiedClass) {
+ m_fullyQualifiedClass = fullyQualifiedClass;
+
+ int indexOfLastDot = fullyQualifiedClass.lastIndexOf('.');
+ if(indexOfLastDot >= 0) {
+ m_packageName = fullyQualifiedClass.substring(0, indexOfLastDot);
+ m_className = fullyQualifiedClass.substring(indexOfLastDot + 1);
+ } else {
+ m_packageName = "";
+ m_className = fullyQualifiedClass;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return m_fullyQualifiedClass;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toSimpleString() {
+ return m_className;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hash(m_packageName, m_className);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null) {
+ return false;
+ }
+
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ FailedPluginClassDetail other = (FailedPluginClassDetail) obj;
+ return Objects.equals(m_packageName, other.m_packageName)
+ && Objects.equals(m_className, other.m_className);
+ }
+ }
+}
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheckRegistry.java
b/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheckRegistry.java
index 52ccc7e..44d8cba 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheckRegistry.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/checks/UpgradeCheckRegistry.java
@@ -18,6 +18,7 @@
package org.apache.ambari.server.checks;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
@@ -25,6 +26,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
+import java.util.stream.Collectors;
import org.apache.ambari.annotations.UpgradeCheckInfo;
import org.apache.ambari.server.AmbariException;
@@ -80,9 +82,10 @@ public class UpgradeCheckRegistry {
new PreUpgradeCheckComparator());
/**
- * The upgrade checks discovered on a per-stack, per-upgrade pack basis.
+ * Represents the upgrade checks (both those which were able to be loaded and
+ * which failed to be loaded) which were discovered in the upgrade pack.
*/
- private final Map<UpgradePack, Set<UpgradeCheck>> m_pluginChecks = new
HashMap<>();
+ private final Map<UpgradePack, PluginUpgradeChecks> m_pluginChecks = new
HashMap<>();
/**
* Register an upgrade check.
@@ -130,11 +133,13 @@ public class UpgradeCheckRegistry {
// for any checks defined in the upgrade pack, add them since they have
been
// explicitely defined
- Set<UpgradeCheck> pluginChecks = m_pluginChecks.get(upgradePack);
+ PluginUpgradeChecks pluginChecks = m_pluginChecks.get(upgradePack);
// see if the upgrade checks have been processes for this pack yet
if (null == pluginChecks) {
- pluginChecks = new TreeSet<>(new PreUpgradeCheckComparator());
+ pluginChecks = new PluginUpgradeChecks(new TreeSet<>(new
PreUpgradeCheckComparator()),
+ new TreeSet<>());
+
m_pluginChecks.put(upgradePack, pluginChecks);
List<String> pluginCheckClassNames = upgradePack.getPrerequisiteChecks();
@@ -145,12 +150,26 @@ public class UpgradeCheckRegistry {
final Set<UpgradeCheck> combinedUpgradeChecks = new TreeSet<>(new
PreUpgradeCheckComparator());
combinedUpgradeChecks.addAll(builtInRequiredChecks);
- combinedUpgradeChecks.addAll(pluginChecks);
+ combinedUpgradeChecks.addAll(pluginChecks.m_loadedChecks);
return new LinkedList<>(combinedUpgradeChecks);
}
/**
+ * Gets all of the upgrade check classes defined in upgrade packs which were
+ * not able to be loaded and instantiated.
+ *
+ * @return all of the failed upgrade check classes.
+ */
+ public Set<String> getFailedPluginClassNames() {
+ Collection<PluginUpgradeChecks> pluginUpgradeChecks =
m_pluginChecks.values();
+
+ return pluginUpgradeChecks.stream()
+ .flatMap(plugins -> plugins.m_failedChecks.stream())
+ .collect(Collectors.toSet());
+ }
+
+ /**
* Uses the library classloader from the the target stack in order to find
any
* plugin-in {@link UpgradeCheck}s which are declared in the upgrade pack.
*
@@ -161,7 +180,7 @@ public class UpgradeCheckRegistry {
*/
@SuppressWarnings("unchecked")
private void loadPluginUpgradeChecksFromStack(UpgradePack upgradePack,
- Set<UpgradeCheck> pluginChecks) throws AmbariException {
+ PluginUpgradeChecks pluginChecks) throws AmbariException {
List<String> pluginCheckClassNames = upgradePack.getPrerequisiteChecks();
StackId ownerStackId = upgradePack.getOwnerStackId();
StackInfo stackInfo = metainfoProvider.get().getStack(ownerStackId);
@@ -174,11 +193,14 @@ public class UpgradeCheckRegistry {
pluginCheckClassName);
UpgradeCheck upgradeCheck =
m_injector.getInstance(upgradeCheckClass);
- pluginChecks.add(upgradeCheck);
+ pluginChecks.m_loadedChecks.add(upgradeCheck);
LOG.info("Registered pre-upgrade check {} for stack {}",
upgradeCheckClass, ownerStackId);
} catch (Exception exception) {
LOG.error("Unable to load the upgrade check {}",
pluginCheckClassName, exception);
+
+ // keep track of the failed check
+ pluginChecks.m_failedChecks.add(pluginCheckClassName);
}
}
} else {
@@ -257,4 +279,36 @@ public class UpgradeCheckRegistry {
return clazz1.getName().compareTo(clazz2.getName());
}
}
+
+ /**
+ * Encapsulates information about which plugins could and could not be loaded
+ * from a stack.
+ */
+ public static final class PluginUpgradeChecks {
+ /**
+ * The upgrade checks discovered on a per-stack, per-upgrade pack basis.
+ */
+ private final Set<UpgradeCheck> m_loadedChecks;
+
+ /**
+ * The upgrade checks discovered on a per-stack, per-upgrade pack basis
+ * which could not be loaded from the stack's 3rd party library
+ * {@link ClassLoader}.
+ */
+ private final Set<String> m_failedChecks;
+
+ /**
+ * Constructor.
+ *
+ * @param loadedChecks
+ * the checks which have been successfully loaded from the stack.
+ * @param failedChecks
+ * the checks which failed to load from the stack and cannot run.
+ */
+ private PluginUpgradeChecks(Set<UpgradeCheck> loadedChecks, Set<String>
failedChecks) {
+ m_loadedChecks = loadedChecks;
+ m_failedChecks = failedChecks;
+ }
+
+ }
}
diff --git
a/ambari-server/src/test/java/org/apache/ambari/server/checks/PluginChecksLoadedCheckTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/checks/PluginChecksLoadedCheckTest.java
new file mode 100644
index 0000000..980d6c1
--- /dev/null
+++
b/ambari-server/src/test/java/org/apache/ambari/server/checks/PluginChecksLoadedCheckTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.ambari.server.checks;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.ambari.spi.upgrade.UpgradeCheckRequest;
+import org.apache.ambari.spi.upgrade.UpgradeCheckResult;
+import org.apache.ambari.spi.upgrade.UpgradeCheckStatus;
+import org.apache.ambari.spi.upgrade.UpgradeType;
+import org.apache.commons.lang.StringUtils;
+import org.easymock.EasyMockSupport;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Sets;
+import com.google.inject.Provider;
+
+/**
+ * Tests for {@link PluginChecksLoadedCheck}
+ */
+public class PluginChecksLoadedCheckTest extends EasyMockSupport {
+
+ private final PluginChecksLoadedCheck m_check = new
PluginChecksLoadedCheck();
+ private final UpgradeCheckRegistry m_upgradeCheckRegistry = createNiceMock(
+ UpgradeCheckRegistry.class);
+
+ @Before
+ public void before() throws Exception {
+
+ m_check.m_upgradeCheckRegistryProvider = new
Provider<UpgradeCheckRegistry>() {
+ @Override
+ public UpgradeCheckRegistry get() {
+ return m_upgradeCheckRegistry;
+ }
+ };
+ }
+
+ /**
+ * @throws Exception
+ */
+ @Test
+ public void testPerform() throws Exception {
+ Set<String> failedClasses = Sets.newHashSet("foo.bar.Baz", "foo.bar.Baz2");
+ expect(m_upgradeCheckRegistry.getFailedPluginClassNames()).andReturn(
+ failedClasses).atLeastOnce();
+
+ replayAll();
+
+ UpgradeCheckRequest request = new UpgradeCheckRequest(null,
UpgradeType.ROLLING, null, null);
+ UpgradeCheckResult check = m_check.perform(request);
+
+ Assert.assertEquals(UpgradeCheckStatus.WARNING, check.getStatus());
+ List<Object> failedDetails = check.getFailedDetail();
+ assertEquals(2, failedDetails.size());
+ assertEquals(2, check.getFailedOn().size());
+ assertTrue(check.getFailedOn().contains("Baz"));
+
+ verifyAll();
+ }
+
+ /**
+ * @throws Exception
+ */
+ @Test
+ public void testPerformWithSuccess() throws Exception {
+ expect(m_upgradeCheckRegistry.getFailedPluginClassNames()).andReturn(
+ new HashSet<>()).atLeastOnce();
+ replayAll();
+
+ UpgradeCheckRequest request = new UpgradeCheckRequest(null,
UpgradeType.ROLLING, null, null);
+ UpgradeCheckResult check = m_check.perform(request);
+
+ Assert.assertEquals(UpgradeCheckStatus.PASS, check.getStatus());
+ Assert.assertTrue(StringUtils.isBlank(check.getFailReason()));
+
+ verifyAll();
+ }
+}
diff --git
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/PreUpgradeCheckResourceProviderTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/PreUpgradeCheckResourceProviderTest.java
index 4f5e298..631e7ec 100644
---
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/PreUpgradeCheckResourceProviderTest.java
+++
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/PreUpgradeCheckResourceProviderTest.java
@@ -227,7 +227,7 @@ public class PreUpgradeCheckResourceProviderTest extends
EasyMockSupport {
// types. The value being asserted here is a combination of built-in checks
// which are required for the upgrade type as well as any provided checks
// discovered in the stack
- Assert.assertEquals(19, resources.size());
+ Assert.assertEquals(20, resources.size());
// find the service check provided by the library classloader and verify
it ran
Resource customUpgradeCheck = null;