From d6627cda9d90055ca8eb05f0d3c920ba7e016d4c Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 26 Jul 2018 20:02:13 -0400 Subject: [PATCH] YARN-8429. Improve diagnostic message when artifact is not set properly. Contributed by Gour Saha (cherry picked from commit 8d3c068e59fdddd18e3f8260713fee83c458aa1d) --- .../exceptions/RestApiErrorMessages.java | 6 +- .../provider/AbstractClientProvider.java | 14 ++-- .../defaultImpl/DefaultClientProvider.java | 26 +++++--- .../provider/docker/DockerClientProvider.java | 15 +++-- .../tarball/TarballClientProvider.java | 27 ++++---- .../yarn/service/utils/ServiceApiUtil.java | 4 +- .../yarn/service/TestServiceApiUtil.java | 9 ++- .../providers/TestAbstractClientProvider.java | 29 ++++---- .../providers/TestDefaultClientProvider.java | 66 +++++++++++++++++++ 9 files changed, 140 insertions(+), 56 deletions(-) create mode 100644 hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/providers/TestDefaultClientProvider.java diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/exceptions/RestApiErrorMessages.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/exceptions/RestApiErrorMessages.java index 5b3c72cae4a..f10d884e4ee 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/exceptions/RestApiErrorMessages.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/exceptions/RestApiErrorMessages.java @@ -50,6 +50,10 @@ public interface RestApiErrorMessages { "Artifact id (like docker image name) is either empty or not provided"; String ERROR_ARTIFACT_ID_FOR_COMP_INVALID = ERROR_ARTIFACT_ID_INVALID + ERROR_SUFFIX_FOR_COMPONENT; + String ERROR_ARTIFACT_PATH_FOR_COMP_INVALID = "For component %s with %s " + + "artifact, path does not exist: %s"; + String ERROR_CONFIGFILE_DEST_FILE_FOR_COMP_NOT_ABSOLUTE = "For component %s " + + "with %s artifact, dest_file must be a relative path: %s"; String ERROR_RESOURCE_INVALID = "Resource is not provided"; String ERROR_RESOURCE_FOR_COMP_INVALID = @@ -89,7 +93,7 @@ public interface RestApiErrorMessages { String ERROR_ABSENT_NUM_OF_INSTANCE = "Num of instances should appear either globally or per component"; String ERROR_ABSENT_LAUNCH_COMMAND = - "Launch_command is required when type is not DOCKER"; + "launch_command is required when type is not DOCKER"; String ERROR_QUICKLINKS_FOR_COMP_INVALID = "Quicklinks specified at" + " component level, needs corresponding values set at service level"; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/AbstractClientProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/AbstractClientProvider.java index d16c698d6a6..0145cee586b 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/AbstractClientProvider.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/AbstractClientProvider.java @@ -68,18 +68,18 @@ public abstract class AbstractClientProvider { * Validate the artifact. * @param artifact */ - public abstract void validateArtifact(Artifact artifact, FileSystem - fileSystem) throws IOException; + public abstract void validateArtifact(Artifact artifact, String compName, + FileSystem fileSystem) throws IOException; - protected abstract void validateConfigFile(ConfigFile configFile, FileSystem - fileSystem) throws IOException; + protected abstract void validateConfigFile(ConfigFile configFile, + String compName, FileSystem fileSystem) throws IOException; /** * Validate the config files. * @param configFiles config file list * @param fs file system */ - public void validateConfigFiles(List configFiles, + public void validateConfigFiles(List configFiles, String compName, FileSystem fs) throws IOException { Set destFileSet = new HashSet<>(); @@ -128,7 +128,7 @@ public abstract class AbstractClientProvider { } if (StringUtils.isEmpty(file.getDestFile())) { - throw new IllegalArgumentException("Dest_file is empty."); + throw new IllegalArgumentException("dest_file is empty."); } if (destFileSet.contains(file.getDestFile())) { @@ -144,7 +144,7 @@ public abstract class AbstractClientProvider { } // provider-specific validation - validateConfigFile(file, fs); + validateConfigFile(file, compName, fs); } } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/defaultImpl/DefaultClientProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/defaultImpl/DefaultClientProvider.java index 0920a9ce114..999a8dc9cb2 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/defaultImpl/DefaultClientProvider.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/defaultImpl/DefaultClientProvider.java @@ -17,30 +17,36 @@ */ package org.apache.hadoop.yarn.service.provider.defaultImpl; -import org.apache.hadoop.fs.FileSystem; -import org.apache.hadoop.yarn.service.provider.AbstractClientProvider; -import org.apache.hadoop.yarn.service.api.records.Artifact; -import org.apache.hadoop.yarn.service.api.records.ConfigFile; - import java.io.IOException; import java.nio.file.Paths; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.yarn.service.api.records.Artifact; +import org.apache.hadoop.yarn.service.api.records.ConfigFile; +import org.apache.hadoop.yarn.service.exceptions.RestApiErrorMessages; +import org.apache.hadoop.yarn.service.provider.AbstractClientProvider; + +import com.google.common.annotations.VisibleForTesting; + public class DefaultClientProvider extends AbstractClientProvider { public DefaultClientProvider() { } @Override - public void validateArtifact(Artifact artifact, FileSystem fileSystem) { + public void validateArtifact(Artifact artifact, String compName, + FileSystem fileSystem) { } @Override - protected void validateConfigFile(ConfigFile configFile, FileSystem - fileSystem) throws IOException { + @VisibleForTesting + public void validateConfigFile(ConfigFile configFile, String compName, + FileSystem fileSystem) throws IOException { // validate dest_file is not absolute if (Paths.get(configFile.getDestFile()).isAbsolute()) { - throw new IllegalArgumentException( - "Dest_file must not be absolute path: " + configFile.getDestFile()); + throw new IllegalArgumentException(String.format( + RestApiErrorMessages.ERROR_CONFIGFILE_DEST_FILE_FOR_COMP_NOT_ABSOLUTE, + compName, "no", configFile.getDestFile())); } } } \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/docker/DockerClientProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/docker/DockerClientProvider.java index d4a2254ff42..d680fa08663 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/docker/DockerClientProvider.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/docker/DockerClientProvider.java @@ -35,19 +35,20 @@ public class DockerClientProvider extends AbstractClientProvider } @Override - public void validateArtifact(Artifact artifact, FileSystem fileSystem) { + public void validateArtifact(Artifact artifact, String compName, + FileSystem fileSystem) { if (artifact == null) { - throw new IllegalArgumentException( - RestApiErrorMessages.ERROR_ARTIFACT_INVALID); + throw new IllegalArgumentException(String.format( + RestApiErrorMessages.ERROR_ARTIFACT_FOR_COMP_INVALID, compName)); } if (StringUtils.isEmpty(artifact.getId())) { - throw new IllegalArgumentException( - RestApiErrorMessages.ERROR_ARTIFACT_ID_INVALID); + throw new IllegalArgumentException(String.format( + RestApiErrorMessages.ERROR_ARTIFACT_ID_FOR_COMP_INVALID, compName)); } } @Override - protected void validateConfigFile(ConfigFile configFile, FileSystem - fileSystem) throws IOException { + protected void validateConfigFile(ConfigFile configFile, String compName, + FileSystem fileSystem) throws IOException { } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/tarball/TarballClientProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/tarball/TarballClientProvider.java index 01f7b209aae..4f153eeca16 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/tarball/TarballClientProvider.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/tarball/TarballClientProvider.java @@ -36,30 +36,33 @@ public class TarballClientProvider extends AbstractClientProvider } @Override - public void validateArtifact(Artifact artifact, FileSystem fs) - throws IOException { + public void validateArtifact(Artifact artifact, String compName, + FileSystem fs) throws IOException { if (artifact == null) { - throw new IllegalArgumentException( - RestApiErrorMessages.ERROR_ARTIFACT_INVALID); + throw new IllegalArgumentException(String.format( + RestApiErrorMessages.ERROR_ARTIFACT_FOR_COMP_INVALID, compName)); } if (StringUtils.isEmpty(artifact.getId())) { - throw new IllegalArgumentException( - RestApiErrorMessages.ERROR_ARTIFACT_ID_INVALID); + throw new IllegalArgumentException(String.format( + RestApiErrorMessages.ERROR_ARTIFACT_ID_FOR_COMP_INVALID, compName)); } Path p = new Path(artifact.getId()); if (!fs.exists(p)) { - throw new IllegalArgumentException( "Artifact tarball does not exist " - + artifact.getId()); + throw new IllegalArgumentException(String.format( + RestApiErrorMessages.ERROR_ARTIFACT_PATH_FOR_COMP_INVALID, compName, + Artifact.TypeEnum.TARBALL.name(), artifact.getId())); } } @Override - protected void validateConfigFile(ConfigFile configFile, FileSystem - fileSystem) throws IOException { + protected void validateConfigFile(ConfigFile configFile, String compName, + FileSystem fileSystem) throws IOException { // validate dest_file is not absolute if (Paths.get(configFile.getDestFile()).isAbsolute()) { - throw new IllegalArgumentException( - "Dest_file must not be absolute path: " + configFile.getDestFile()); + throw new IllegalArgumentException(String.format( + RestApiErrorMessages.ERROR_CONFIGFILE_DEST_FILE_FOR_COMP_NOT_ABSOLUTE, + compName, Artifact.TypeEnum.TARBALL.name(), + configFile.getDestFile())); } } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java index 6b18203175f..a646f06aa05 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/ServiceApiUtil.java @@ -273,7 +273,7 @@ public class ServiceApiUtil { AbstractClientProvider compClientProvider = ProviderFactory .getClientProvider(comp.getArtifact()); - compClientProvider.validateArtifact(comp.getArtifact(), fs); + compClientProvider.validateArtifact(comp.getArtifact(), comp.getName(), fs); if (comp.getLaunchCommand() == null && (comp.getArtifact() == null || comp .getArtifact().getType() != Artifact.TypeEnum.DOCKER)) { @@ -290,7 +290,7 @@ public class ServiceApiUtil { + ": " + comp.getNumberOfContainers(), comp.getName())); } compClientProvider.validateConfigFiles(comp.getConfiguration() - .getFiles(), fs); + .getFiles(), comp.getName(), fs); MonitorUtils.getProbe(comp.getReadinessCheck()); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/TestServiceApiUtil.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/TestServiceApiUtil.java index ae031d4aad9..47b2803eb36 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/TestServiceApiUtil.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/TestServiceApiUtil.java @@ -227,14 +227,16 @@ public class TestServiceApiUtil { // no artifact id fails with default type Artifact artifact = new Artifact(); app.setArtifact(artifact); - Component comp = ServiceTestUtils.createComponent("comp1"); + String compName = "comp1"; + Component comp = ServiceTestUtils.createComponent(compName); app.setComponents(Collections.singletonList(comp)); try { ServiceApiUtil.validateAndResolveService(app, sfs, CONF_DNS_ENABLED); Assert.fail(EXCEPTION_PREFIX + "service with no artifact id"); } catch (IllegalArgumentException e) { - assertEquals(ERROR_ARTIFACT_ID_INVALID, e.getMessage()); + assertEquals(String.format(ERROR_ARTIFACT_ID_FOR_COMP_INVALID, compName), + e.getMessage()); } // no artifact id fails with SERVICE type @@ -252,7 +254,8 @@ public class TestServiceApiUtil { ServiceApiUtil.validateAndResolveService(app, sfs, CONF_DNS_ENABLED); Assert.fail(EXCEPTION_PREFIX + "service with no artifact id"); } catch (IllegalArgumentException e) { - assertEquals(ERROR_ARTIFACT_ID_INVALID, e.getMessage()); + assertEquals(String.format(ERROR_ARTIFACT_ID_FOR_COMP_INVALID, compName), + e.getMessage()); } // everything valid here diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/providers/TestAbstractClientProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/providers/TestAbstractClientProvider.java index 1d6be910c55..ae626086f98 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/providers/TestAbstractClientProvider.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/providers/TestAbstractClientProvider.java @@ -45,12 +45,12 @@ public class TestAbstractClientProvider { private static class ClientProvider extends AbstractClientProvider { @Override - public void validateArtifact(Artifact artifact, FileSystem fileSystem) - throws IOException { + public void validateArtifact(Artifact artifact, String compName, + FileSystem fileSystem) throws IOException { } @Override - protected void validateConfigFile(ConfigFile configFile, + protected void validateConfigFile(ConfigFile configFile, String compName, FileSystem fileSystem) throws IOException { } } @@ -62,33 +62,34 @@ public class TestAbstractClientProvider { FileStatus mockFileStatus = mock(FileStatus.class); when(mockFs.exists(anyObject())).thenReturn(true); + String compName = "sleeper"; ConfigFile configFile = new ConfigFile(); List configFiles = new ArrayList<>(); configFiles.add(configFile); try { - clientProvider.validateConfigFiles(configFiles, mockFs); + clientProvider.validateConfigFiles(configFiles, compName, mockFs); Assert.fail(EXCEPTION_PREFIX + "null file type"); } catch (IllegalArgumentException e) { } configFile.setType(ConfigFile.TypeEnum.TEMPLATE); try { - clientProvider.validateConfigFiles(configFiles, mockFs); + clientProvider.validateConfigFiles(configFiles, compName, mockFs); Assert.fail(EXCEPTION_PREFIX + "empty src_file for type template"); } catch (IllegalArgumentException e) { } configFile.setSrcFile("srcfile"); try { - clientProvider.validateConfigFiles(configFiles, mockFs); + clientProvider.validateConfigFiles(configFiles, compName, mockFs); Assert.fail(EXCEPTION_PREFIX + "empty dest file"); } catch (IllegalArgumentException e) { } configFile.setDestFile("destfile"); try { - clientProvider.validateConfigFiles(configFiles, mockFs); + clientProvider.validateConfigFiles(configFiles, compName, mockFs); } catch (IllegalArgumentException e) { Assert.fail(NO_EXCEPTION_PREFIX + e.getMessage()); } @@ -99,21 +100,21 @@ public class TestAbstractClientProvider { configFile.setDestFile("path/destfile2"); configFiles.add(configFile); try { - clientProvider.validateConfigFiles(configFiles, mockFs); + clientProvider.validateConfigFiles(configFiles, compName, mockFs); Assert.fail(EXCEPTION_PREFIX + "dest file with multiple path elements"); } catch (IllegalArgumentException e) { } configFile.setDestFile("/path/destfile2"); try { - clientProvider.validateConfigFiles(configFiles, mockFs); + clientProvider.validateConfigFiles(configFiles, compName, mockFs); } catch (IllegalArgumentException e) { Assert.fail(NO_EXCEPTION_PREFIX + e.getMessage()); } configFile.setDestFile("destfile"); try { - clientProvider.validateConfigFiles(configFiles, mockFs); + clientProvider.validateConfigFiles(configFiles, compName, mockFs); Assert.fail(EXCEPTION_PREFIX + "duplicate dest file"); } catch (IllegalArgumentException e) { } @@ -125,14 +126,14 @@ public class TestAbstractClientProvider { configFile.setDestFile("path/destfile3"); configFiles.add(configFile); try { - clientProvider.validateConfigFiles(configFiles, mockFs); + clientProvider.validateConfigFiles(configFiles, compName, mockFs); Assert.fail(EXCEPTION_PREFIX + "dest file with multiple path elements"); } catch (IllegalArgumentException e) { } configFile.setDestFile("/path/destfile3"); try { - clientProvider.validateConfigFiles(configFiles, mockFs); + clientProvider.validateConfigFiles(configFiles, compName, mockFs); Assert.fail(EXCEPTION_PREFIX + "src file should be specified"); } catch (IllegalArgumentException e) { } @@ -140,7 +141,7 @@ public class TestAbstractClientProvider { //should succeed configFile.setSrcFile("srcFile"); configFile.setDestFile("destfile3"); - clientProvider.validateConfigFiles(configFiles, mockFs); + clientProvider.validateConfigFiles(configFiles, compName, mockFs); when(mockFileStatus.isDirectory()).thenReturn(true); when(mockFs.getFileStatus(new Path("srcFile"))) @@ -154,7 +155,7 @@ public class TestAbstractClientProvider { configFiles.add(configFile); try { - clientProvider.validateConfigFiles(configFiles, mockFs); + clientProvider.validateConfigFiles(configFiles, compName, mockFs); Assert.fail(EXCEPTION_PREFIX + "src file is a directory"); } catch (IllegalArgumentException e) { } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/providers/TestDefaultClientProvider.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/providers/TestDefaultClientProvider.java new file mode 100644 index 00000000000..366515c8b42 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/providers/TestDefaultClientProvider.java @@ -0,0 +1,66 @@ +/* + * 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.hadoop.yarn.service.providers; + +import static org.mockito.Matchers.anyObject; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; + +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.yarn.service.api.records.ConfigFile; +import org.apache.hadoop.yarn.service.exceptions.RestApiErrorMessages; +import org.apache.hadoop.yarn.service.provider.defaultImpl.DefaultClientProvider; +import org.junit.Assert; +import org.junit.Test; + +public class TestDefaultClientProvider { + private static final String EXCEPTION_PREFIX = "Should have thrown " + + "exception: "; + private static final String NO_EXCEPTION_PREFIX = "Should not have thrown " + + "exception: "; + + @Test + public void testConfigFile() throws IOException { + DefaultClientProvider defaultClientProvider = new DefaultClientProvider(); + FileSystem mockFs = mock(FileSystem.class); + when(mockFs.exists(anyObject())).thenReturn(true); + + String compName = "sleeper"; + ConfigFile configFile = new ConfigFile(); + configFile.setDestFile("/var/tmp/a.txt"); + + try { + defaultClientProvider.validateConfigFile(configFile, compName, mockFs); + Assert.fail(EXCEPTION_PREFIX + " dest_file must be relative"); + } catch (IllegalArgumentException e) { + String actualMsg = String.format( + RestApiErrorMessages.ERROR_CONFIGFILE_DEST_FILE_FOR_COMP_NOT_ABSOLUTE, + compName, "no", configFile.getDestFile()); + Assert.assertEquals(actualMsg, e.getLocalizedMessage()); + } + + configFile.setDestFile("../a.txt"); + try { + defaultClientProvider.validateConfigFile(configFile, compName, mockFs); + } catch (IllegalArgumentException e) { + Assert.fail(NO_EXCEPTION_PREFIX + e.getLocalizedMessage()); + } + } +}