diff --git a/build.gradle b/build.gradle index 7b58a53..5a44d09 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,10 @@ sonarqube { } } +jacoco { + toolVersion = "0.8.6" +} + jacocoTestReport { reports { xml.enabled true @@ -87,16 +91,16 @@ configurations { dependencies { implementation ( 'com.fasterxml.jackson.core:jackson-databind:2.10.1', - 'com.squareup.okhttp3:okhttp:3.14.9', + 'com.squareup.okhttp3:okhttp:3.14.7', 'org.apache.logging.log4j:log4j-api:2.13.2', 'org.apache.logging.log4j:log4j-core:2.13.2', - 'org.rundeck:rundeck-core:3.3.4-20201007', - 'org.rundeck:rundeck-storage-api:3.3.4-20201007', + 'org.rundeck:rundeck-core:3.3.6-20201111', + 'org.rundeck:rundeck-storage-api:3.3.6-20201111', ) testImplementation ( 'com.squareup.okhttp3:mockwebserver:3.11.0', 'junit:junit:4.12', - 'org.mockito:mockito-core:3.+', + 'org.mockito:mockito-core:3.6+', 'org.slf4j:slf4j-simple:1.7.30+', ) } @@ -134,5 +138,5 @@ jar { } wrapper { - gradleVersion = '6.6.1' + gradleVersion = '6.7.1' } diff --git a/src/main/java/com/bioraft/rundeck/rancher/IResolverUtil.java b/src/main/java/com/bioraft/rundeck/rancher/IResolverUtil.java new file mode 100644 index 0000000..1a17030 --- /dev/null +++ b/src/main/java/com/bioraft/rundeck/rancher/IResolverUtil.java @@ -0,0 +1,109 @@ +package com.bioraft.rundeck.rancher; + +import com.dtolabs.rundeck.core.common.IFramework; +import com.dtolabs.rundeck.core.common.INodeEntry; +import com.dtolabs.rundeck.core.common.IRundeckProject; +import com.dtolabs.rundeck.core.execution.impl.jsch.JschNodeExecutor; + +/* + * Copyright 2016 SimplifyOps, Inc. (http://simplifyops.com) + * + * 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. + */ + +/** + * Created by greg on 3/19/15. + */ +public class IResolverUtil { + /** + * Resolve a node/project/framework property by first checking node attributes named X, then project properties + * named "project.X", then framework properties named "framework.X". If none of those exist, return the default + * value + */ + public static String resolveProperty( + final String nodeAttribute, + final String defaultValue, + final INodeEntry node, + final IRundeckProject frameworkProject, + final IFramework framework + ) + { + if (null != node.getAttributes().get(nodeAttribute)) { + return node.getAttributes().get(nodeAttribute); + } else if (frameworkProject.hasProperty(JschNodeExecutor.PROJ_PROP_PREFIX + nodeAttribute) + && !"".equals(frameworkProject.getProperty(JschNodeExecutor.PROJ_PROP_PREFIX + nodeAttribute))) { + return frameworkProject.getProperty(JschNodeExecutor.PROJ_PROP_PREFIX + nodeAttribute); + } else if (framework.getPropertyLookup().hasProperty(JschNodeExecutor.FWK_PROP_PREFIX + nodeAttribute)) { + return framework.getPropertyLookup().getProperty(JschNodeExecutor.FWK_PROP_PREFIX + nodeAttribute); + } else { + return defaultValue; + } + } + + public static int resolveIntProperty( + final String attribute, + final int defaultValue, + final INodeEntry iNodeEntry, + final IRundeckProject frameworkProject, + final IFramework framework + ) + { + + int value = defaultValue; + final String string = resolveProperty(attribute, null, iNodeEntry, frameworkProject, framework); + if (null != string) { + try { + value = Integer.parseInt(string); + } catch (NumberFormatException e) { + } + } + return value; + } + + public static long resolveLongProperty( + final String attribute, + final long defaultValue, + final INodeEntry iNodeEntry, + final IRundeckProject frameworkProject, + final IFramework framework + ) + { + + long value = defaultValue; + final String string = resolveProperty(attribute, null, iNodeEntry, frameworkProject, framework); + if (null != string) { + try { + value = Long.parseLong(string); + } catch (NumberFormatException e) { + } + } + return value; + } + + public static boolean resolveBooleanProperty( + final String attribute, + final boolean defaultValue, + final INodeEntry iNodeEntry, + final IRundeckProject frameworkProject, + final IFramework framework + ) + { + + boolean value = defaultValue; + final String string = resolveProperty(attribute, null, iNodeEntry, frameworkProject, framework); + if (null != string) { + value = Boolean.parseBoolean(string); + } + return value; + } +} diff --git a/src/main/java/com/bioraft/rundeck/rancher/RancherFileCopier.java b/src/main/java/com/bioraft/rundeck/rancher/RancherFileCopier.java index 9c43f75..708a3fb 100644 --- a/src/main/java/com/bioraft/rundeck/rancher/RancherFileCopier.java +++ b/src/main/java/com/bioraft/rundeck/rancher/RancherFileCopier.java @@ -26,7 +26,9 @@ import com.dtolabs.rundeck.core.Constants; import com.dtolabs.rundeck.core.common.Framework; +import com.dtolabs.rundeck.core.common.IFramework; import com.dtolabs.rundeck.core.common.INodeEntry; +import com.dtolabs.rundeck.core.common.IRundeckProject; import com.dtolabs.rundeck.core.execution.ExecutionContext; import com.dtolabs.rundeck.core.execution.ExecutionLogger; import com.dtolabs.rundeck.core.execution.impl.common.BaseFileCopier; @@ -129,11 +131,13 @@ private String copyFile(final ExecutionContext context, final File scriptFile, f String message = "copying file: '" + absPath + "' to: '" + node.getNodename() + ":" + remoteFile + "'"; logger.log(DEBUG_LEVEL, message); - Framework framework = context.getFramework(); - String project = context.getFrameworkProject(); - String searchPath = framework.getProjectProperty(project, PROJ_RANCHER_CLI_PATH); - if ((searchPath == null || searchPath.equals("")) && framework.hasProperty(FMWK_RANCHER_CLI_PATH)) { - searchPath = framework.getProperty(FMWK_RANCHER_CLI_PATH); + IFramework framework = context.getIFramework(); + IRundeckProject project = framework.getFrameworkProjectMgr().getFrameworkProject(context.getFrameworkProject()); + String searchPath = ""; + if (project.hasProperty(PROJ_RANCHER_CLI_PATH)) { + searchPath = project.getProperty(PROJ_RANCHER_CLI_PATH); + } else if (framework.getPropertyLookup().hasProperty(FMWK_RANCHER_CLI_PATH)) { + searchPath = framework.getPropertyLookup().getProperty(FMWK_RANCHER_CLI_PATH); } try { @@ -162,10 +166,14 @@ private String getRemoteFile(final String destinationPath, final ExecutionContex String identity = null != context.getDataContext() && null != context.getDataContext().get("job") ? context.getDataContext().get("job").get("execid") : null; - return BaseFileCopier.generateRemoteFilepathForNode(node, - context.getFramework().getFrameworkProjectMgr().getFrameworkProject(context.getFrameworkProject()), - context.getFramework(), (null != scriptFile ? scriptFile.getName() : "dispatch-script"), null, - identity); + return BaseFileCopier.generateRemoteFilepathForNode( + node, + context.getIFramework().getFrameworkProjectMgr().getFrameworkProject(context.getFrameworkProject()), + context.getIFramework(), + (null != scriptFile ? scriptFile.getName() : "dispatch-script"), + null, + identity + ); } else { return destinationPath; } diff --git a/src/main/java/com/bioraft/rundeck/rancher/RancherNodeExecutorPlugin.java b/src/main/java/com/bioraft/rundeck/rancher/RancherNodeExecutorPlugin.java index 262def1..0f77ba6 100644 --- a/src/main/java/com/bioraft/rundeck/rancher/RancherNodeExecutorPlugin.java +++ b/src/main/java/com/bioraft/rundeck/rancher/RancherNodeExecutorPlugin.java @@ -27,7 +27,6 @@ import com.dtolabs.rundeck.core.execution.service.NodeExecutor; import com.dtolabs.rundeck.core.execution.service.NodeExecutorResult; import com.dtolabs.rundeck.core.execution.service.NodeExecutorResultImpl; -import com.dtolabs.rundeck.core.execution.utils.ResolverUtil; import com.dtolabs.rundeck.core.execution.workflow.steps.StepFailureReason; import com.dtolabs.rundeck.core.plugins.Plugin; import com.dtolabs.rundeck.core.plugins.configuration.*; @@ -120,9 +119,13 @@ public NodeExecutorResult executeCommand(final ExecutionContext context, final S Map jobContext = context.getDataContext().get("job"); String temp = this.baseName(command, jobContext); - int timeout = ResolverUtil.resolveIntProperty(RANCHER_CONFIG_EXECUTOR_TIMEOUT, 300, node, - context.getFramework().getFrameworkProjectMgr().getFrameworkProject(context.getFrameworkProject()), - context.getFramework()); + int timeout = IResolverUtil.resolveIntProperty( + RANCHER_CONFIG_EXECUTOR_TIMEOUT, + 300, + node, + context.getIFramework().getFrameworkProjectMgr().getFrameworkProject(context.getFrameworkProject()), + context.getIFramework() + ); if (nodeAttributes.get("type").equals("service")) { // "self": "https://rancher.example.com/v2-beta/projects/1a10/services/1s56" diff --git a/src/test/java/com/bioraft/rundeck/rancher/RancherFileCopierTest.java b/src/test/java/com/bioraft/rundeck/rancher/RancherFileCopierTest.java index a94c223..654b1dd 100644 --- a/src/test/java/com/bioraft/rundeck/rancher/RancherFileCopierTest.java +++ b/src/test/java/com/bioraft/rundeck/rancher/RancherFileCopierTest.java @@ -2,6 +2,7 @@ import com.dtolabs.rundeck.core.common.Framework; import com.dtolabs.rundeck.core.common.INodeEntry; +import com.dtolabs.rundeck.core.common.IRundeckProject; import com.dtolabs.rundeck.core.common.ProjectManager; import com.dtolabs.rundeck.core.execution.ExecutionContext; import com.dtolabs.rundeck.core.execution.service.FileCopierException; @@ -23,8 +24,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static com.bioraft.rundeck.rancher.Constants.CONFIG_ACCESSKEY_PATH; -import static com.bioraft.rundeck.rancher.Constants.CONFIG_SECRETKEY_PATH; +import static com.bioraft.rundeck.rancher.Constants.*; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.*; @@ -32,6 +32,8 @@ @RunWith(MockitoJUnitRunner.class) public class RancherFileCopierTest { + static final String PROJECT_NAME = "mock"; + @Mock INodeEntry node; @@ -59,8 +61,8 @@ public class RancherFileCopierTest { @Mock ProjectManager projectManager; -// @Mock -// IRundeckProject rundeckProject; + @Mock + IRundeckProject rundeckProject; @Mock IPropertyLookup propertyLookup; @@ -73,7 +75,13 @@ public void setUp() { when(storageTree.getResource(anyString())).thenReturn(treeResource); when(executionContext.getStorageTree()).thenReturn(storageTree); when(executionContext.getExecutionLogger()).thenReturn(logger); - when(executionContext.getFramework()).thenReturn(framework); + when(executionContext.getIFramework()).thenReturn(framework); + when(executionContext.getFrameworkProject()).thenReturn(PROJECT_NAME); + when(framework.getFrameworkProjectMgr()).thenReturn(projectManager); + when(framework.getPropertyLookup()).thenReturn(propertyLookup); + when(projectManager.getFrameworkProject(PROJECT_NAME)).thenReturn(rundeckProject); + when(rundeckProject.hasProperty(PROJ_RANCHER_CLI_PATH)).thenReturn(false); + when(propertyLookup.hasProperty(FMWK_RANCHER_CLI_PATH)).thenReturn(false); // when(framework.getProjectProperty(anyString(), anyString())).thenReturn(""); // when(framework.createFrameworkNode()).thenReturn(host); diff --git a/src/test/java/com/bioraft/rundeck/rancher/RancherNodeExecutorPluginTest.java b/src/test/java/com/bioraft/rundeck/rancher/RancherNodeExecutorPluginTest.java index 6f254e8..852a6a2 100644 --- a/src/test/java/com/bioraft/rundeck/rancher/RancherNodeExecutorPluginTest.java +++ b/src/test/java/com/bioraft/rundeck/rancher/RancherNodeExecutorPluginTest.java @@ -111,7 +111,7 @@ public void serviceIsNotYetSupported() throws IOException, InterruptedException when(storage.loadStoragePathData(nodeAttributes.get(CONFIG_ACCESSKEY_PATH))).thenReturn(accessKey); when(storage.loadStoragePathData(nodeAttributes.get(CONFIG_SECRETKEY_PATH))).thenReturn(secretKey); - when(executionContext.getFramework()).thenReturn(framework); + when(executionContext.getIFramework()).thenReturn(framework); when(framework.getFrameworkProjectMgr()).thenReturn(projectManager); when(executionContext.getExecutionLogger()).thenReturn(executionLogger); @@ -173,7 +173,7 @@ public void testExecutorEmpty() throws IOException, InterruptedException { when(storage.loadStoragePathData(nodeAttributes.get(CONFIG_ACCESSKEY_PATH))).thenReturn("access"); when(storage.loadStoragePathData(nodeAttributes.get(CONFIG_SECRETKEY_PATH))).thenReturn("secret"); - when(executionContext.getFramework()).thenReturn(framework); + when(executionContext.getIFramework()).thenReturn(framework); when(framework.getFrameworkProjectMgr()).thenReturn(projectManager); when(executionContext.getExecutionLogger()).thenReturn(executionLogger); @@ -216,7 +216,7 @@ public void testExecutor(String fileContents) throws IOException, InterruptedExc when(storage.loadStoragePathData(nodeAttributes.get(CONFIG_ACCESSKEY_PATH))).thenReturn("access"); when(storage.loadStoragePathData(nodeAttributes.get(CONFIG_SECRETKEY_PATH))).thenReturn("secret"); - when(executionContext.getFramework()).thenReturn(framework); + when(executionContext.getIFramework()).thenReturn(framework); when(framework.getFrameworkProjectMgr()).thenReturn(projectManager); when(executionContext.getExecutionLogger()).thenReturn(executionLogger); @@ -244,7 +244,7 @@ public void testJobIOFailure() throws IOException, InterruptedException { when(storage.loadStoragePathData(nodeAttributes.get(CONFIG_ACCESSKEY_PATH))).thenReturn("access"); when(storage.loadStoragePathData(nodeAttributes.get(CONFIG_SECRETKEY_PATH))).thenReturn("secret"); - when(executionContext.getFramework()).thenReturn(framework); + when(executionContext.getIFramework()).thenReturn(framework); when(framework.getFrameworkProjectMgr()).thenReturn(projectManager); when(executionContext.getExecutionLogger()).thenReturn(executionLogger); @@ -275,7 +275,7 @@ public void testInterruptedJob() throws IOException, InterruptedException { when(storage.loadStoragePathData(nodeAttributes.get(CONFIG_ACCESSKEY_PATH))).thenReturn("access"); when(storage.loadStoragePathData(nodeAttributes.get(CONFIG_SECRETKEY_PATH))).thenReturn("secret"); - when(executionContext.getFramework()).thenReturn(framework); + when(executionContext.getIFramework()).thenReturn(framework); when(framework.getFrameworkProjectMgr()).thenReturn(projectManager); when(executionContext.getExecutionLogger()).thenReturn(executionLogger); @@ -305,7 +305,7 @@ public void testReadIOFailure() throws IOException, InterruptedException { when(storage.loadStoragePathData(nodeAttributes.get(CONFIG_ACCESSKEY_PATH))).thenReturn("access"); when(storage.loadStoragePathData(nodeAttributes.get(CONFIG_SECRETKEY_PATH))).thenReturn("secret"); - when(executionContext.getFramework()).thenReturn(framework); + when(executionContext.getIFramework()).thenReturn(framework); when(framework.getFrameworkProjectMgr()).thenReturn(projectManager); when(executionContext.getExecutionLogger()).thenReturn(executionLogger); @@ -335,7 +335,7 @@ public void testInterruptedRead() throws IOException, InterruptedException { when(storage.loadStoragePathData(nodeAttributes.get(CONFIG_ACCESSKEY_PATH))).thenReturn("access"); when(storage.loadStoragePathData(nodeAttributes.get(CONFIG_SECRETKEY_PATH))).thenReturn("secret"); - when(executionContext.getFramework()).thenReturn(framework); + when(executionContext.getIFramework()).thenReturn(framework); when(framework.getFrameworkProjectMgr()).thenReturn(projectManager); when(executionContext.getExecutionLogger()).thenReturn(executionLogger);