This is an automated email from the ASF dual-hosted git repository.
oleewere pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ambari-infra.git
The following commit(s) were added to refs/heads/master by this push:
new 07a56bc AMBARI-24969 - Infra Manager: REST api cleanup (#20)
07a56bc is described below
commit 07a56bc2709c4daa3a762260604bbbe28cc24d64
Author: kasakrisz <[email protected]>
AuthorDate: Sat Dec 1 12:49:27 2018 +0100
AMBARI-24969 - Infra Manager: REST api cleanup (#20)
* AMBARI-24969 - Infra Manager: REST api cleanup
* AMBARI-24969 - Infra Manager: REST api cleanup - fix build
---
ambari-infra-manager-it/pom.xml | 84 ++-
.../java/org/apache/ambari/infra/InfraClient.java | 133 +---
.../ambari/infra/steps/AbstractInfraSteps.java | 21 +-
.../apache/ambari/infra/steps/ExportJobsSteps.java | 48 +-
.../{log4j.properties => log4j2-test.properties} | 19 +-
ambari-infra-manager/.gitignore | 4 +-
ambari-infra-manager/docs/api/swagger.yaml | 784 ---------------------
ambari-infra-manager/pom.xml | 50 +-
.../ambari/infra/conf/FsPermissionConverter.java | 37 -
.../infra/conf/StaticResourceConfiguration.java | 4 +-
.../infra/doc/InfraManagerApiDocStorage.java | 92 ---
.../ambari/infra/job/archive/DocumentExporter.java | 10 +-
.../ambari/infra/job/cleanup/TaskHistoryWiper.java | 11 +-
.../infra/job/deleting/DocumentWiperTasklet.java | 3 +-
.../OffsetDateTimeToStringConverter.java} | 20 +-
.../infra/json/StringToDurationConverter.java | 12 +-
.../infra/json/StringToFsPermissionConverter.java | 11 +-
.../apache/ambari/infra/manager/JobManager.java | 39 +-
.../DateUtil.java} | 21 +-
.../infra/model/ExecutionContextResponse.java | 4 +-
...textResponse.java => ISO8601DateFormatter.java} | 35 +-
.../ambari/infra/model/JobDetailsResponse.java | 53 --
.../infra/model/JobExecutionDetailsResponse.java | 20 +-
.../infra/model/JobExecutionInfoResponse.java | 183 +++--
.../infra/model/JobExecutionRestartRequest.java | 3 +
.../infra/model/JobExecutionStopRequest.java | 3 +
.../infra/model/JobInstanceDetailsResponse.java | 30 +-
.../infra/model/JobInstanceStartRequest.java | 5 +-
.../infra/model/StepExecutionContextResponse.java | 15 +-
.../infra/model/StepExecutionInfoResponse.java | 127 ++--
.../infra/model/StepExecutionProgressResponse.java | 12 +-
.../infra/model/wrapper/JobExecutionData.java | 118 ----
.../infra/model/wrapper/StepExecutionData.java | 133 ----
.../apache/ambari/infra/rest/ApiDocResource.java | 56 --
.../org/apache/ambari/infra/rest/JobResource.java | 10 +-
.../src/main/resources/infra-manager.properties | 1 +
.../src/main/resources/swagger/swagger.html | 2 +-
.../infra/job/archive/DocumentExporterTest.java | 31 +-
.../infra/model/ISO8601DateFormatterTest.java | 50 ++
39 files changed, 595 insertions(+), 1699 deletions(-)
diff --git a/ambari-infra-manager-it/pom.xml b/ambari-infra-manager-it/pom.xml
index f1f296b..8745713 100644
--- a/ambari-infra-manager-it/pom.xml
+++ b/ambari-infra-manager-it/pom.xml
@@ -33,9 +33,12 @@
<properties>
<jbehave.version>4.0.5</jbehave.version>
- <failsafe-plugin.version>2.20</failsafe-plugin.version>
- <infra-manager.docker.host>localhost</infra-manager.docker.host>
+ <failsafePlugin.version>2.20</failsafePlugin.version>
+ <infraManager.docker.host>localhost</infraManager.docker.host>
<stories.location>NONE</stories.location>
+ <okhttp.version>2.7.5</okhttp.version>
+
<generatedSourcesPath>${project.build.directory}/generated-sources</generatedSourcesPath>
+ <generatedSourcesJavaPath>main/java</generatedSourcesJavaPath>
</properties>
<dependencies>
@@ -167,6 +170,32 @@
<artifactId>log4j-core</artifactId>
<version>2.11.1</version>
</dependency>
+ <!-- swagger client related -->
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.swagger</groupId>
+ <artifactId>swagger-annotations</artifactId>
+ <version>1.5.21</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.gsonfire</groupId>
+ <artifactId>gson-fire</artifactId>
+ <version>1.8.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>okhttp</artifactId>
+ <version>${okhttp.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>logging-interceptor</artifactId>
+ <version>${okhttp.version}</version>
+ </dependency>
</dependencies>
<build>
@@ -182,6 +211,53 @@
<directory>src/test/resources</directory>
</testResource>
</testResources>
+ <plugins>
+ <plugin>
+ <groupId>io.swagger</groupId>
+ <artifactId>swagger-codegen-maven-plugin</artifactId>
+ <version>2.3.1</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ <configuration>
+
<inputSpec>${project.parent.basedir}/ambari-infra-manager/src/main/resources/swagger/swagger.yaml</inputSpec>
+ <language>java</language>
+ <generateApiTests>false</generateApiTests>
+ <generateModelTests>false</generateModelTests>
+ <output>${generatedSourcesPath}</output>
+ <configOptions>
+ <sourceFolder>${generatedSourcesJavaPath}</sourceFolder>
+ <apiPackage>org.apache.ambari.infra.client.api</apiPackage>
+
<modelPackage>org.apache.ambari.infra.client.model</modelPackage>
+
<invokerPackage>org.apache.ambari.infra.client.invoker</invokerPackage>
+ <dateLibrary>java8</dateLibrary>
+ </configOptions>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>3.0.0</version>
+ <executions>
+ <execution>
+ <id>add-generated-source</id>
+ <phase>initialize</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+
<source>${generatedSourcesPath}/${generatedSourcesJavaPath}</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
</build>
<profiles>
@@ -197,7 +273,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
- <version>${failsafe-plugin.version}</version>
+ <version>${failsafePlugin.version}</version>
<executions>
<execution>
<id>run-integration-tests</id>
@@ -212,7 +288,7 @@
</includes>
<systemPropertyVariables>
<log4j.configuration>file:${project.build.testOutputDirectory}/log4j.properties</log4j.configuration>
- <docker.host>${infra-manager.docker.host}</docker.host>
+ <docker.host>${infraManager.docker.host}</docker.host>
<backend.stories.location>${stories.location}</backend.stories.location>
</systemPropertyVariables>
</configuration>
diff --git
a/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/InfraClient.java
b/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/InfraClient.java
index 1b0b4cf..bce3c7e 100644
---
a/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/InfraClient.java
+++
b/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/InfraClient.java
@@ -18,134 +18,59 @@
*/
package org.apache.ambari.infra;
-import static org.apache.commons.lang.StringUtils.isBlank;
+import java.util.List;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.charset.Charset;
-import java.util.HashMap;
-import java.util.Map;
+import org.apache.ambari.infra.client.api.JobsApi;
+import org.apache.ambari.infra.client.invoker.ApiClient;
+import org.apache.ambari.infra.client.invoker.ApiException;
+import org.apache.ambari.infra.client.model.JobExecutionInfoResponse;
-import org.apache.commons.io.IOUtils;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.CredentialsProvider;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpDelete;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpRequestBase;
-import org.apache.http.client.utils.URIBuilder;
-import org.apache.http.impl.client.BasicCredentialsProvider;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-// TODO: use swagger
-public class InfraClient implements AutoCloseable {
- private static final Logger logger = LogManager.getLogger(InfraClient.class);
-
- private final CloseableHttpClient httpClient;
- private final URI baseUrl;
+public class InfraClient {
+ private final JobsApi jobsApi;
public InfraClient(String baseUrl) {
+ ApiClient apiClient = new ApiClient().setBasePath(baseUrl);
+ apiClient.setUsername("admin");
+ apiClient.setPassword("admin");
+ this.jobsApi = new JobsApi(apiClient);
+ }
+
+ public List<String> getJobs() {
try {
- this.baseUrl = new URI(baseUrl);
- } catch (URISyntaxException e) {
+ return jobsApi.getAllJobNames();
+ } catch (ApiException e) {
throw new RuntimeException(e);
}
-
- CredentialsProvider provider = new BasicCredentialsProvider();
- UsernamePasswordCredentials credentials
- = new UsernamePasswordCredentials("admin", "admin");
- provider.setCredentials(AuthScope.ANY, credentials);
-
- httpClient = HttpClientBuilder.create()
- .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
- .setDefaultCredentialsProvider(provider)
- .build();
- }
-
- @Override
- public void close() throws Exception {
- httpClient.close();
}
- // TODO: return job data
- public void getJobs() {
- execute(new HttpGet(baseUrl));
- }
-
- private HttpResponse execute(HttpRequestBase post) {
- try (CloseableHttpResponse response = httpClient.execute(post)) {
- String responseBodyText =
IOUtils.toString(response.getEntity().getContent(), Charset.defaultCharset());
- int statusCode = response.getStatusLine().getStatusCode();
- logger.info("Response code {} body {} ", statusCode, responseBodyText);
- if (!(200 <= statusCode && statusCode <= 299))
- throw new RuntimeException("Error while executing http request: " +
responseBodyText);
- return new HttpResponse(statusCode, responseBodyText);
- } catch (ClientProtocolException e) {
+ public JobExecutionInfoResponse startJob(String jobName, String parameters) {
+ try {
+ return jobsApi.startJob(jobName, parameters);
+ } catch (ApiException e) {
throw new RuntimeException(e);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
}
}
- public JobExecutionInfo startJob(String jobName, String parameters) {
- URIBuilder uriBuilder = new URIBuilder(baseUrl);
- uriBuilder.setScheme("http");
- uriBuilder.setPath(uriBuilder.getPath() + "/" + jobName);
- if (!isBlank(parameters))
- uriBuilder.addParameter("params", parameters);
+ public void restartJob(String jobName, long jobId) {
try {
- String responseText = execute(new
HttpPost(uriBuilder.build())).getBody();
- Map<String, Object> responseContent = new
ObjectMapper().readValue(responseText, new
TypeReference<HashMap<String,Object>>() {});
- if (!responseContent.containsKey("jobId"))
- throw new NullPointerException("jobId is not found in start job
responseContent");
- if (!responseContent.containsKey("jobExecutionData"))
- throw new NullPointerException("jobExecutionData is not found in start
job responseContent");
- if (!((Map)responseContent.get("jobExecutionData")).containsKey("id"))
- throw new NullPointerException("id is not found in jobExecutionData");
- return new JobExecutionInfo(responseContent.get("jobId").toString(),
((Map)responseContent.get("jobExecutionData")).get("id").toString());
- } catch (URISyntaxException | JsonParseException | JsonMappingException e)
{
+ jobsApi.restartJobInstance(jobName, jobId, "RESTART");
+ } catch (ApiException e) {
throw new RuntimeException(e);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
}
}
- public void restartJob(String jobName, String jobId) {
- URIBuilder uriBuilder = new URIBuilder(baseUrl);
- uriBuilder.setScheme("http");
- uriBuilder.setPath(String.format("%s/%s/%s/executions",
uriBuilder.getPath(), jobName, jobId));
- uriBuilder.addParameter("operation", "RESTART");
+ public void stopJob(long jobExecutionId) {
try {
- HttpResponse httpResponse = execute(new HttpPost(uriBuilder.build()));
- if (httpResponse.getCode() != 200)
- throw new RuntimeException(httpResponse.getBody());
- } catch (URISyntaxException e) {
+ jobsApi.stopOrAbandonJobExecution(jobExecutionId, "STOP");
+ } catch (ApiException e) {
throw new RuntimeException(e);
}
}
- public void stopJob(String jobExecutionId) {
- URIBuilder uriBuilder = new URIBuilder(baseUrl);
- uriBuilder.setScheme("http");
- uriBuilder.setPath(String.format("%s/executions/%s", uriBuilder.getPath(),
jobExecutionId));
- uriBuilder.addParameter("operation", "STOP");
+ public boolean isRunning(String jobName) {
try {
- execute(new HttpDelete(uriBuilder.build()));
- } catch (URISyntaxException e) {
+ return !jobsApi.getExecutionIdsByJobName(jobName).isEmpty();
+ } catch (ApiException e) {
throw new RuntimeException(e);
}
}
diff --git
a/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/steps/AbstractInfraSteps.java
b/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/steps/AbstractInfraSteps.java
index 9ecf489..985fda5 100644
---
a/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/steps/AbstractInfraSteps.java
+++
b/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/steps/AbstractInfraSteps.java
@@ -47,17 +47,16 @@ public abstract class AbstractInfraSteps {
private static final int INFRA_MANAGER_PORT = 61890;
private static final int FAKE_S3_PORT = 4569;
- private static final int HDFS_PORT = 9000;
protected static final String S3_BUCKET_NAME = "testbucket";
private String ambariFolder;
private String shellScriptLocation;
- private String dockerHost;
private S3Client s3client;
private int documentId = 0;
private Solr solr;
+ private InfraClient infraClient;
public InfraClient getInfraClient() {
- return new InfraClient(String.format("http://%s:%d/api/v1/jobs",
dockerHost, INFRA_MANAGER_PORT));
+ return infraClient;
}
public Solr getSolr() {
@@ -89,13 +88,16 @@ public abstract class AbstractInfraSteps {
FileUtils.cleanDirectory(new File(localDataFolder));
}
+ logger.info("Copy resources");
FileUtils.copyDirectory(new ClassPathResource("conf").getFile(), new
File(getInfraManagerConfDir()));
shellScriptLocation = ambariFolder +
"/ambari-infra/ambari-infra-manager/docker/infra-manager-docker-compose.sh";
logger.info("Create new docker container for testing Ambari Infra Manager
...");
runCommand(new String[]{shellScriptLocation, "start"});
- dockerHost = getDockerHost();
+ String dockerHost = getDockerHost();
+
+ this.infraClient = new InfraClient(String.format("http://%s:%d/api/v1",
dockerHost, INFRA_MANAGER_PORT));
solr = new Solr();
solr.waitUntilSolrIsUp();
@@ -110,11 +112,10 @@ public abstract class AbstractInfraSteps {
checkInfraManagerReachable();
}
- private void checkInfraManagerReachable() throws Exception {
- try (InfraClient httpClient = getInfraClient()) {
- doWithin(30, "Start Ambari Infra Manager", httpClient::getJobs);
- logger.info("Ambari Infra Manager is up and running");
- }
+ private void checkInfraManagerReachable() {
+ InfraClient infraClient = getInfraClient();
+ doWithin(30, "Start Ambari Infra Manager", infraClient::getJobs);
+ logger.info("Ambari Infra Manager is up and running");
}
protected SolrInputDocument addDocument(OffsetDateTime logtime) {
@@ -149,7 +150,7 @@ public abstract class AbstractInfraSteps {
solrInputDocument.addField("logtime", new
Date(logtime.toInstant().toEpochMilli()));
solrInputDocument.addField("evtTime", new
Date(logtime.toInstant().toEpochMilli()));
solrInputDocument.addField("_ttl_", "+7DAYS");
- solrInputDocument.addField("_expire_at_", "2017-12-15T10:23:19.106Z");
+ solrInputDocument.addField("_expire_at_", new
Date(logtime.plusDays(7).toInstant().toEpochMilli()));
solr.add(solrInputDocument);
return solrInputDocument;
}
diff --git
a/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/steps/ExportJobsSteps.java
b/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/steps/ExportJobsSteps.java
index e67762e..0825290 100644
---
a/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/steps/ExportJobsSteps.java
+++
b/ambari-infra-manager-it/src/test/java/org/apache/ambari/infra/steps/ExportJobsSteps.java
@@ -40,8 +40,8 @@ import java.util.Map;
import java.util.Set;
import org.apache.ambari.infra.InfraClient;
-import org.apache.ambari.infra.JobExecutionInfo;
import org.apache.ambari.infra.S3Client;
+import org.apache.ambari.infra.client.model.JobExecutionInfoResponse;
import
org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -58,7 +58,7 @@ public class ExportJobsSteps extends AbstractInfraSteps {
private static final Logger logger =
LogManager.getLogger(ExportJobsSteps.class);
private Set<String> documentIds = new HashSet<>();
- private Map<String, JobExecutionInfo> launchedJobs = new HashMap<>();
+ private Map<String, JobExecutionInfoResponse> launchedJobs = new HashMap<>();
@Given("$count documents in solr")
public void addDocuments(int count) {
@@ -94,32 +94,24 @@ public class ExportJobsSteps extends AbstractInfraSteps {
@When("start $jobName job with parameters $parameters after $waitSec
seconds")
public void startJob(String jobName, String parameters, int waitSec) throws
Exception {
Thread.sleep(waitSec * 1000);
- try (InfraClient httpClient = getInfraClient()) {
- JobExecutionInfo jobExecutionInfo = httpClient.startJob(jobName,
parameters);
- logger.info("Job {} started: {}", jobName, jobExecutionInfo);
- launchedJobs.put(jobName, jobExecutionInfo);
- }
+ JobExecutionInfoResponse jobExecutionInfo =
getInfraClient().startJob(jobName, parameters);
+ logger.info("Job {} started: {}", jobName, jobExecutionInfo);
+ launchedJobs.put(jobName, jobExecutionInfo);
}
@When("restart $jobName job within $waitSec seconds")
public void restartJob(String jobName, int waitSec) {
- doWithin(waitSec, "Restarting job " + jobName, () -> {
- try (InfraClient httpClient = getInfraClient()) {
- httpClient.restartJob(jobName, launchedJobs.get(jobName).getJobId());
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- });
+ doWithin(waitSec, "Restarting job " + jobName, () ->
+ getInfraClient().restartJob(jobName,
launchedJobs.get(jobName).getJobInstanceId()));
}
@When("stop job $jobName after at least $count file exists in s3 with
filename containing text $text within $waitSec seconds")
public void stopJob(String jobName, int count, String text, int waitSec)
throws Exception {
S3Client s3Client = getS3client();
doWithin(waitSec, "check uploaded files to s3", () ->
s3Client.listObjectKeys(text).size() > count);
-
- try (InfraClient httpClient = getInfraClient()) {
- httpClient.stopJob(launchedJobs.get(jobName).getExecutionId());
- }
+ InfraClient infraClient = getInfraClient();
+ infraClient.stopJob(launchedJobs.get(jobName).getJobExecutionId());
+ doWithin(waitSec, String.format("Wait for job %s stops", jobName), () ->
infraClient.isRunning(jobName));
}
@When("delete file with key $key from s3")
@@ -182,7 +174,7 @@ public class ExportJobsSteps extends AbstractInfraSteps {
@Then("Check $count files exists on local filesystem with filenames
containing the text $text in the folder $path for job $jobName")
public void checkNumberOfFilesOnLocalFilesystem(long count, String text,
String path, String jobName) {
- File destinationDirectory = new File(getLocalDataFolder(),
path.replace("${jobId}", launchedJobs.get(jobName).getJobId()));
+ File destinationDirectory = new File(getLocalDataFolder(),
path.replace("${jobId}",
Long.toString(launchedJobs.get(jobName).getJobInstanceId())));
logger.info("Destination directory path: {}",
destinationDirectory.getAbsolutePath());
doWithin(5, "Destination directory exists", destinationDirectory::exists);
@@ -216,7 +208,21 @@ public class ExportJobsSteps extends AbstractInfraSteps {
}
@AfterScenario
- public void waitABit() throws InterruptedException {
- Thread.sleep(5000);
+ public void waitForJobStops() throws InterruptedException {
+ InfraClient infraClient = getInfraClient();
+ doWithin(20, "Stop all launched jobs", () -> {
+ int runningJobCount = 0;
+ for (String jobName : launchedJobs.keySet()) {
+ if (launchedJobs.get(jobName) == null)
+ continue;
+ if (!infraClient.isRunning(jobName)) {
+ launchedJobs.put(jobName, null);
+ }
+ else {
+ ++runningJobCount;
+ }
+ }
+ return runningJobCount == 0;
+ });
}
}
diff --git a/ambari-infra-manager-it/src/test/resources/log4j.properties
b/ambari-infra-manager-it/src/test/resources/log4j2-test.properties
similarity index 57%
rename from ambari-infra-manager-it/src/test/resources/log4j.properties
rename to ambari-infra-manager-it/src/test/resources/log4j2-test.properties
index 956bc63..4e488fd 100644
--- a/ambari-infra-manager-it/src/test/resources/log4j.properties
+++ b/ambari-infra-manager-it/src/test/resources/log4j2-test.properties
@@ -9,8 +9,17 @@
# 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.
-log4j.rootLogger=INFO, stdout
-log4j.appender.stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.stdout.Target=System.out
-log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p
%c{1}:%L - %m%n
\ No newline at end of file
+
+status = error
+dest = err
+name = PropertiesConfig
+
+appender.console.type = Console
+appender.console.name = STDOUT
+appender.console.layout.type = PatternLayout
+appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
+appender.console.filter.threshold.type = ThresholdFilter
+appender.console.filter.threshold.level = info
+
+rootLogger.level = info
+rootLogger.appenderRef.stdout.ref = STDOUT
diff --git a/ambari-infra-manager/.gitignore b/ambari-infra-manager/.gitignore
index 4aece78..dd3661e 100644
--- a/ambari-infra-manager/.gitignore
+++ b/ambari-infra-manager/.gitignore
@@ -3,4 +3,6 @@ out/*
Profile
.env
test-out
-test.db
\ No newline at end of file
+test.db
+**/swagger/swagger.json
+**/swagger/swagger.yaml
\ No newline at end of file
diff --git a/ambari-infra-manager/docs/api/swagger.yaml
b/ambari-infra-manager/docs/api/swagger.yaml
deleted file mode 100644
index 6fad22d..0000000
--- a/ambari-infra-manager/docs/api/swagger.yaml
+++ /dev/null
@@ -1,784 +0,0 @@
----
-swagger: "2.0"
-info:
- description: "Manager component for Ambari Infra"
- version: "1.0.0"
- title: "Infra Manager REST API"
- license:
- name: "Apache 2.0"
- url: "http://www.apache.org/licenses/LICENSE-2.0.html"
-basePath: "/api/v1"
-tags:
-- name: "jobs"
-schemes:
-- "http"
-- "https"
-paths:
- /jobs:
- get:
- tags:
- - "jobs"
- summary: "Get all jobs"
- description: ""
- operationId: "getAllJobs"
- produces:
- - "application/json"
- parameters:
- - name: "page"
- in: "query"
- required: false
- type: "integer"
- default: 0
- format: "int32"
- - name: "size"
- in: "query"
- required: false
- type: "integer"
- default: 20
- format: "int32"
- responses:
- 200:
- description: "successful operation"
- schema:
- type: "array"
- items:
- $ref: "#/definitions/JobInfo"
- /jobs/executions:
- delete:
- tags:
- - "jobs"
- summary: "Stop all job executions."
- description: ""
- operationId: "stopAll"
- produces:
- - "application/json"
- parameters: []
- responses:
- 200:
- description: "successful operation"
- schema:
- type: "integer"
- format: "int32"
- /jobs/executions/{jobExecutionId}:
- get:
- tags:
- - "jobs"
- summary: "Get job and step details for job execution instance."
- description: ""
- operationId: "getExecutionInfo"
- produces:
- - "application/json"
- parameters:
- - name: "jobExecutionId"
- in: "path"
- required: true
- type: "integer"
- format: "int64"
- responses:
- 200:
- description: "successful operation"
- schema:
- $ref: "#/definitions/JobExecutionDetailsResponse"
- delete:
- tags:
- - "jobs"
- summary: "Stop or abandon a running job execution."
- description: ""
- operationId: "stopOrAbandonJobExecution"
- produces:
- - "application/json"
- parameters:
- - name: "jobExecutionId"
- in: "path"
- required: true
- type: "integer"
- format: "int64"
- - name: "operation"
- in: "query"
- required: true
- type: "string"
- enum:
- - "STOP"
- - "ABANDON"
- responses:
- 200:
- description: "successful operation"
- schema:
- $ref: "#/definitions/JobExecutionInfoResponse"
- /jobs/executions/{jobExecutionId}/context:
- get:
- tags:
- - "jobs"
- summary: "Get execution context for specific job."
- description: ""
- operationId: "getExecutionContextByJobExecId"
- produces:
- - "application/json"
- parameters:
- - name: "jobExecutionId"
- in: "path"
- required: true
- type: "integer"
- format: "int64"
- responses:
- 200:
- description: "successful operation"
- schema:
- $ref: "#/definitions/ExecutionContextResponse"
- /jobs/executions/{jobExecutionId}/steps/{stepExecutionId}:
- get:
- tags:
- - "jobs"
- summary: "Get step execution details."
- description: ""
- operationId: "getStepExecution"
- produces:
- - "application/json"
- parameters:
- - name: "jobExecutionId"
- in: "path"
- required: true
- type: "integer"
- format: "int64"
- - name: "stepExecutionId"
- in: "path"
- required: true
- type: "integer"
- format: "int64"
- responses:
- 200:
- description: "successful operation"
- schema:
- $ref: "#/definitions/StepExecutionInfoResponse"
- /jobs/executions/{jobExecutionId}/steps/{stepExecutionId}/execution-context:
- get:
- tags:
- - "jobs"
- summary: "Get the execution context of step execution."
- description: ""
- operationId: "getStepExecutionContext"
- produces:
- - "application/json"
- parameters:
- - name: "jobExecutionId"
- in: "path"
- required: true
- type: "integer"
- format: "int64"
- - name: "stepExecutionId"
- in: "path"
- required: true
- type: "integer"
- format: "int64"
- responses:
- 200:
- description: "successful operation"
- schema:
- $ref: "#/definitions/StepExecutionContextResponse"
- /jobs/executions/{jobExecutionId}/steps/{stepExecutionId}/progress:
- get:
- tags:
- - "jobs"
- summary: "Get progress of step execution."
- description: ""
- operationId: "getStepExecutionProgress"
- produces:
- - "application/json"
- parameters:
- - name: "jobExecutionId"
- in: "path"
- required: true
- type: "integer"
- format: "int64"
- - name: "stepExecutionId"
- in: "path"
- required: true
- type: "integer"
- format: "int64"
- responses:
- 200:
- description: "successful operation"
- schema:
- $ref: "#/definitions/StepExecutionProgressResponse"
- /jobs/info/names:
- get:
- tags:
- - "jobs"
- summary: "Get all job names"
- description: ""
- operationId: "getAllJobNames"
- produces:
- - "application/json"
- parameters: []
- responses:
- 200:
- description: "successful operation"
- schema:
- type: "array"
- uniqueItems: true
- items:
- type: "string"
- /jobs/{jobName}:
- post:
- tags:
- - "jobs"
- summary: "Start a new job instance by job name."
- description: ""
- operationId: "startJob"
- produces:
- - "application/json"
- parameters:
- - name: "jobName"
- in: "path"
- required: true
- type: "string"
- - name: "params"
- in: "query"
- required: false
- type: "string"
- responses:
- 200:
- description: "successful operation"
- schema:
- $ref: "#/definitions/JobExecutionInfoResponse"
- /jobs/{jobName}/executions:
- get:
- tags:
- - "jobs"
- summary: "Get the id values of all the running job instances."
- description: ""
- operationId: "getExecutionIdsByJobName"
- produces:
- - "application/json"
- parameters:
- - name: "jobName"
- in: "path"
- required: true
- type: "string"
- responses:
- 200:
- description: "successful operation"
- schema:
- type: "array"
- uniqueItems: true
- items:
- type: "integer"
- format: "int64"
- /jobs/{jobName}/info:
- get:
- tags:
- - "jobs"
- summary: "Get job details by job name."
- description: ""
- operationId: "getJobDetails"
- produces:
- - "application/json"
- parameters:
- - name: "page"
- in: "query"
- required: false
- type: "integer"
- default: 0
- format: "int32"
- - name: "size"
- in: "query"
- required: false
- type: "integer"
- default: 20
- format: "int32"
- - name: "jobName"
- in: "path"
- required: true
- type: "string"
- responses:
- 200:
- description: "successful operation"
- schema:
- $ref: "#/definitions/JobDetailsResponse"
- /jobs/{jobName}/{jobInstanceId}/executions:
- get:
- tags:
- - "jobs"
- summary: "Get execution for job instance."
- description: ""
- operationId: "getExecutionsForInstance"
- produces:
- - "application/json"
- parameters:
- - name: "jobName"
- in: "path"
- required: true
- type: "string"
- - name: "jobInstanceId"
- in: "path"
- required: true
- type: "integer"
- format: "int64"
- responses:
- 200:
- description: "successful operation"
- schema:
- type: "array"
- items:
- $ref: "#/definitions/JobExecutionInfoResponse"
- post:
- tags:
- - "jobs"
- summary: "Restart job instance."
- description: ""
- operationId: "restartJobInstance"
- produces:
- - "application/json"
- parameters:
- - in: "body"
- name: "body"
- required: false
- schema:
- $ref: "#/definitions/JobExecutionRestartRequest"
- responses:
- 200:
- description: "successful operation"
- schema:
- $ref: "#/definitions/JobExecutionInfoResponse"
-definitions:
- JobExecutionData:
- type: "object"
- properties:
- id:
- type: "integer"
- format: "int64"
- executionContext:
- $ref: "#/definitions/ExecutionContext"
- jobInstance:
- $ref: "#/definitions/JobInstance"
- jobId:
- type: "integer"
- format: "int64"
- jobParameters:
- $ref: "#/definitions/JobParameters"
- failureExceptions:
- type: "array"
- items:
- $ref: "#/definitions/Throwable"
- endTime:
- type: "string"
- format: "date-time"
- exitStatus:
- $ref: "#/definitions/ExitStatus"
- createTime:
- type: "string"
- format: "date-time"
- lastUpdated:
- type: "string"
- format: "date-time"
- jobConfigurationName:
- type: "string"
- startTime:
- type: "string"
- format: "date-time"
- status:
- type: "string"
- enum:
- - "COMPLETED"
- - "STARTING"
- - "STARTED"
- - "STOPPING"
- - "STOPPED"
- - "FAILED"
- - "ABANDONED"
- - "UNKNOWN"
- stepExecutionDataList:
- type: "array"
- items:
- $ref: "#/definitions/StepExecutionData"
- JobInstance:
- type: "object"
- properties:
- id:
- type: "integer"
- format: "int64"
- version:
- type: "integer"
- format: "int32"
- jobName:
- type: "string"
- instanceId:
- type: "integer"
- format: "int64"
- StepExecutionData:
- type: "object"
- properties:
- id:
- type: "integer"
- format: "int64"
- jobExecutionId:
- type: "integer"
- format: "int64"
- executionContext:
- $ref: "#/definitions/ExecutionContext"
- stepName:
- type: "string"
- terminateOnly:
- type: "boolean"
- default: false
- failureExceptions:
- type: "array"
- items:
- $ref: "#/definitions/Throwable"
- endTime:
- type: "string"
- format: "date-time"
- exitStatus:
- $ref: "#/definitions/ExitStatus"
- lastUpdated:
- type: "string"
- format: "date-time"
- commitCount:
- type: "integer"
- format: "int32"
- readCount:
- type: "integer"
- format: "int32"
- filterCount:
- type: "integer"
- format: "int32"
- writeCount:
- type: "integer"
- format: "int32"
- readSkipCount:
- type: "integer"
- format: "int32"
- writeSkipCount:
- type: "integer"
- format: "int32"
- processSkipCount:
- type: "integer"
- format: "int32"
- rollbackCount:
- type: "integer"
- format: "int32"
- startTime:
- type: "string"
- format: "date-time"
- status:
- type: "string"
- enum:
- - "COMPLETED"
- - "STARTING"
- - "STARTED"
- - "STOPPING"
- - "STOPPED"
- - "FAILED"
- - "ABANDONED"
- - "UNKNOWN"
- StackTraceElement:
- type: "object"
- properties:
- methodName:
- type: "string"
- fileName:
- type: "string"
- lineNumber:
- type: "integer"
- format: "int32"
- className:
- type: "string"
- nativeMethod:
- type: "boolean"
- default: false
- JobExecutionDetailsResponse:
- type: "object"
- properties:
- jobExecutionInfoResponse:
- $ref: "#/definitions/JobExecutionInfoResponse"
- stepExecutionInfoList:
- type: "array"
- items:
- $ref: "#/definitions/StepExecutionInfoResponse"
- StepExecutionContextResponse:
- type: "object"
- properties:
- executionContextMap:
- type: "object"
- additionalProperties:
- type: "object"
- jobExecutionId:
- type: "integer"
- format: "int64"
- stepExecutionId:
- type: "integer"
- format: "int64"
- stepName:
- type: "string"
- StepExecutionProgress:
- type: "object"
- properties:
- estimatedPercentCompleteMessage:
- $ref: "#/definitions/MessageSourceResolvable"
- estimatedPercentComplete:
- type: "number"
- format: "double"
- ExitStatus:
- type: "object"
- properties:
- exitCode:
- type: "string"
- exitDescription:
- type: "string"
- running:
- type: "boolean"
- default: false
- ExecutionContextResponse:
- type: "object"
- properties:
- jobExecutionId:
- type: "integer"
- format: "int64"
- executionContextMap:
- type: "object"
- additionalProperties:
- type: "object"
- StepExecutionHistory:
- type: "object"
- properties:
- stepName:
- type: "string"
- count:
- type: "integer"
- format: "int32"
- commitCount:
- $ref: "#/definitions/CumulativeHistory"
- rollbackCount:
- $ref: "#/definitions/CumulativeHistory"
- readCount:
- $ref: "#/definitions/CumulativeHistory"
- writeCount:
- $ref: "#/definitions/CumulativeHistory"
- filterCount:
- $ref: "#/definitions/CumulativeHistory"
- readSkipCount:
- $ref: "#/definitions/CumulativeHistory"
- writeSkipCount:
- $ref: "#/definitions/CumulativeHistory"
- processSkipCount:
- $ref: "#/definitions/CumulativeHistory"
- duration:
- $ref: "#/definitions/CumulativeHistory"
- durationPerRead:
- $ref: "#/definitions/CumulativeHistory"
- TimeZone:
- type: "object"
- properties:
- displayName:
- type: "string"
- id:
- type: "string"
- dstsavings:
- type: "integer"
- format: "int32"
- rawOffset:
- type: "integer"
- format: "int32"
- MessageSourceResolvable:
- type: "object"
- properties:
- arguments:
- type: "array"
- items:
- type: "object"
- codes:
- type: "array"
- items:
- type: "string"
- defaultMessage:
- type: "string"
- ExecutionContext:
- type: "object"
- properties:
- dirty:
- type: "boolean"
- default: false
- empty:
- type: "boolean"
- default: false
- StepExecutionInfoResponse:
- type: "object"
- properties:
- id:
- type: "integer"
- format: "int64"
- jobExecutionId:
- type: "integer"
- format: "int64"
- jobName:
- type: "string"
- name:
- type: "string"
- startDate:
- type: "string"
- startTime:
- type: "string"
- duration:
- type: "string"
- durationMillis:
- type: "integer"
- format: "int64"
- exitCode:
- type: "string"
- status:
- type: "string"
- JobExecutionInfoResponse:
- type: "object"
- properties:
- id:
- type: "integer"
- format: "int64"
- stepExecutionCount:
- type: "integer"
- format: "int32"
- jobId:
- type: "integer"
- format: "int64"
- jobName:
- type: "string"
- startDate:
- type: "string"
- startTime:
- type: "string"
- duration:
- type: "string"
- jobExecutionData:
- $ref: "#/definitions/JobExecutionData"
- jobParameters:
- type: "object"
- additionalProperties:
- type: "object"
- jobParametersString:
- type: "string"
- restartable:
- type: "boolean"
- default: false
- abandonable:
- type: "boolean"
- default: false
- stoppable:
- type: "boolean"
- default: false
- timeZone:
- $ref: "#/definitions/TimeZone"
- JobInfo:
- type: "object"
- properties:
- name:
- type: "string"
- executionCount:
- type: "integer"
- format: "int32"
- launchable:
- type: "boolean"
- default: false
- incrementable:
- type: "boolean"
- default: false
- jobInstanceId:
- type: "integer"
- format: "int64"
- JobExecutionRestartRequest:
- type: "object"
- properties:
- jobName:
- type: "string"
- jobInstanceId:
- type: "integer"
- format: "int64"
- operation:
- type: "string"
- enum:
- - "RESTART"
- Throwable:
- type: "object"
- properties:
- cause:
- $ref: "#/definitions/Throwable"
- stackTrace:
- type: "array"
- items:
- $ref: "#/definitions/StackTraceElement"
- message:
- type: "string"
- localizedMessage:
- type: "string"
- suppressed:
- type: "array"
- items:
- $ref: "#/definitions/Throwable"
- JobParameters:
- type: "object"
- properties:
- parameters:
- type: "object"
- additionalProperties:
- $ref: "#/definitions/JobParameter"
- empty:
- type: "boolean"
- default: false
- CumulativeHistory:
- type: "object"
- properties:
- count:
- type: "integer"
- format: "int32"
- min:
- type: "number"
- format: "double"
- max:
- type: "number"
- format: "double"
- standardDeviation:
- type: "number"
- format: "double"
- mean:
- type: "number"
- format: "double"
- JobInstanceDetailsResponse:
- type: "object"
- properties:
- jobInstance:
- $ref: "#/definitions/JobInstance"
- jobExecutionInfoResponseList:
- type: "array"
- items:
- $ref: "#/definitions/JobExecutionInfoResponse"
- JobParameter:
- type: "object"
- properties:
- identifying:
- type: "boolean"
- default: false
- value:
- type: "object"
- type:
- type: "string"
- enum:
- - "STRING"
- - "DATE"
- - "LONG"
- - "DOUBLE"
- StepExecutionProgressResponse:
- type: "object"
- properties:
- stepExecutionProgress:
- $ref: "#/definitions/StepExecutionProgress"
- stepExecutionHistory:
- $ref: "#/definitions/StepExecutionHistory"
- stepExecutionInfoResponse:
- $ref: "#/definitions/StepExecutionInfoResponse"
- JobDetailsResponse:
- type: "object"
- properties:
- jobInfo:
- $ref: "#/definitions/JobInfo"
- jobInstanceDetailsResponseList:
- type: "array"
- items:
- $ref: "#/definitions/JobInstanceDetailsResponse"
diff --git a/ambari-infra-manager/pom.xml b/ambari-infra-manager/pom.xml
index 722bf51..d595f99 100644
--- a/ambari-infra-manager/pom.xml
+++ b/ambari-infra-manager/pom.xml
@@ -30,18 +30,19 @@
<artifactId>ambari-infra-manager</artifactId>
<properties>
- <spring.version>5.1.1.RELEASE</spring.version>
- <spring.security.version>5.1.1.RELEASE</spring.security.version>
+ <spring.version>5.1.3.RELEASE</spring.version>
+ <spring.security.version>5.1.2.RELEASE</spring.security.version>
<spring.ldap.version>2.3.2.RELEASE</spring.ldap.version>
<jersey.version>2.27</jersey.version>
<jetty.version>9.4.11.v20180605</jetty.version>
- <spring-batch.version>3.0.7.RELEASE</spring-batch.version>
+ <spring-batch.version>4.1.0.RELEASE</spring-batch.version>
<sqlite.version>3.8.11.2</sqlite.version>
<spring-data-solr.version>3.0.10.RELEASE</spring-data-solr.version>
<spring-boot.version>2.0.6.RELEASE</spring-boot.version>
<swagger.version>1.5.16</swagger.version>
<jjwt.version>0.6.0</jjwt.version>
<aws-sdk.version>1.11.445</aws-sdk.version>
+ <swagger-maven-plugin-version>3.1.7</swagger-maven-plugin-version>
</properties>
<build>
@@ -117,6 +118,49 @@
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>com.github.kongchen</groupId>
+ <artifactId>swagger-maven-plugin</artifactId>
+ <version>${swagger-maven-plugin-version}</version>
+ <configuration>
+ <apiSources>
+ <apiSource>
+ <springmvc>false</springmvc>
+ <locations>org.apache.ambari.infra.rest</locations>
+ <schemes>
+ <scheme>http</scheme>
+ <scheme>https</scheme>
+ </schemes>
+ <basePath>/api/v1</basePath>
+ <info>
+ <title>Infra Manager REST API</title>
+ <version>1.0.0</version>
+ <description>Ambari Infra Manager REST APIs has inherent
support for querying, sorting and pagination</description>
+ <license>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ <name>Apache License, Version 2.0</name>
+ </license>
+ </info>
+ <outputFormats>yaml,json</outputFormats>
+
<swaggerDirectory>${project.basedir}/src/main/resources/swagger</swaggerDirectory>
+ <securityDefinitions>
+ <securityDefinition>
+ <name>basicAuth</name>
+ <type>basic</type>
+ </securityDefinition>
+ </securityDefinitions>
+ </apiSource>
+ </apiSources>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>compile</phase>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/FsPermissionConverter.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/FsPermissionConverter.java
deleted file mode 100644
index 5e794a7..0000000
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/FsPermissionConverter.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.infra.conf;
-
-import static
org.apache.ambari.infra.json.StringToFsPermissionConverter.toFsPermission;
-
-import javax.annotation.Nullable;
-import javax.inject.Named;
-
-import org.apache.hadoop.fs.permission.FsPermission;
-import
org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
-import org.springframework.core.convert.converter.Converter;
-
-@Named
-@ConfigurationPropertiesBinding
-public class FsPermissionConverter implements Converter<String, FsPermission> {
- @Override
- public FsPermission convert(@Nullable String s) {
- return toFsPermission(s);
- }
-}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/StaticResourceConfiguration.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/StaticResourceConfiguration.java
index f0cd3cf..9651271 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/StaticResourceConfiguration.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/StaticResourceConfiguration.java
@@ -22,11 +22,11 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import
org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import
org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
-import
org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebMvc
@Configuration
-public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {
+public class StaticResourceConfiguration implements WebMvcConfigurer {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/static/",
"classpath:/swagger/","classpath:META-INF/resources/webjars/"
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/doc/InfraManagerApiDocStorage.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/doc/InfraManagerApiDocStorage.java
deleted file mode 100644
index 5ababcc..0000000
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/doc/InfraManagerApiDocStorage.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.infra.doc;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import javax.annotation.PostConstruct;
-import javax.inject.Inject;
-import javax.inject.Named;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-import io.swagger.jaxrs.config.BeanConfig;
-import io.swagger.models.Swagger;
-import io.swagger.models.auth.BasicAuthDefinition;
-import io.swagger.util.Yaml;
-
-@Named
-public class InfraManagerApiDocStorage {
-
- private static final Logger logger =
LogManager.getLogger(InfraManagerApiDocStorage.class);
-
- private final Map<String, Object> swaggerMap = new ConcurrentHashMap<>();
-
- @Inject
- private BeanConfig beanConfig;
-
- @PostConstruct
- private void postConstruct() {
- Thread loadApiDocThread = new Thread("load_swagger_api_doc") {
- @Override
- public void run() {
- logger.info("Start thread to scan REST API doc from endpoints.");
- Swagger swagger = beanConfig.getSwagger();
- swagger.addSecurityDefinition("basicAuth", new BasicAuthDefinition());
- beanConfig.configure(swagger);
- beanConfig.scanAndRead();
- setSwagger(swagger);
- try {
- String yaml = Yaml.mapper().writeValueAsString(swagger);
- StringBuilder b = new StringBuilder();
- String[] parts = yaml.split("\n");
- for (String part : parts) {
- b.append(part);
- b.append("\n");
- }
- setSwaggerYaml(b.toString());
- } catch (Exception e) {
- e.printStackTrace();
- }
- logger.info("Scanning REST API endpoints and generating docs has been
successful.");
- }
- };
- loadApiDocThread.setDaemon(true);
- loadApiDocThread.start();
- }
-
- public Swagger getSwagger() {
- return (Swagger) swaggerMap.get("swaggerObject");
- }
-
- public void setSwagger(final Swagger swagger) {
- swaggerMap.put("swaggerObject", swagger);
- }
-
- public void setSwaggerYaml(final String swaggerYaml) {
- swaggerMap.put("swaggerYaml", swaggerYaml);
- }
-
- public String getSwaggerYaml() {
- return (String) swaggerMap.get("swaggerYaml");
- }
-
-}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExporter.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExporter.java
index f61746d..8c4a067 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExporter.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/archive/DocumentExporter.java
@@ -21,7 +21,6 @@ package org.apache.ambari.infra.job.archive;
import org.apache.ambari.infra.job.JobContextRepository;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
@@ -31,6 +30,7 @@ import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStreamReader;
import org.springframework.batch.repeat.RepeatStatus;
+import org.springframework.lang.NonNull;
public class DocumentExporter implements Tasklet, StepExecutionListener {
@@ -50,12 +50,12 @@ public class DocumentExporter implements Tasklet,
StepExecutionListener {
}
@Override
- public void beforeStep(StepExecution stepExecution) {
+ public void beforeStep(@NonNull StepExecution stepExecution) {
}
@Override
- public ExitStatus afterStep(StepExecution stepExecution) {
+ public ExitStatus afterStep(@NonNull StepExecution stepExecution) {
if (complete) {
return ExitStatus.COMPLETED;
}
@@ -65,7 +65,7 @@ public class DocumentExporter implements Tasklet,
StepExecutionListener {
}
@Override
- public RepeatStatus execute(StepContribution contribution, ChunkContext
chunkContext) throws Exception {
+ public RepeatStatus execute(@NonNull StepContribution contribution, @NonNull
ChunkContext chunkContext) throws Exception {
StepExecution stepExecution =
chunkContext.getStepContext().getStepExecution();
ExecutionContext executionContext = stepExecution.getExecutionContext();
documentReader.open(executionContext);
@@ -77,7 +77,7 @@ public class DocumentExporter implements Tasklet,
StepExecutionListener {
while ((document = documentReader.read()) != null) {
if (writer != null && writtenCount >= writeBlockSize) {
stepExecution =
jobContextRepository.getStepExecution(stepExecution.getJobExecutionId(),
stepExecution.getId());
- if (stepExecution.getJobExecution().getStatus() ==
BatchStatus.STOPPING) {
+ if (stepExecution.isTerminateOnly()) {
logger.info("Received stop signal.");
writer.revert();
writer = null;
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/cleanup/TaskHistoryWiper.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/cleanup/TaskHistoryWiper.java
index 5a296de..2627f4c 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/cleanup/TaskHistoryWiper.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/cleanup/TaskHistoryWiper.java
@@ -28,20 +28,21 @@ import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
+import org.springframework.lang.NonNull;
public class TaskHistoryWiper implements Tasklet {
private static final Logger logger =
LogManager.getLogger(TaskHistoryWiper.class);
- public static final Duration DEFAULT_TTL = Duration.ofHours(1);
+ private static final Duration MINIMUM_TTL = Duration.ofHours(1);
private final InfraJobExecutionDao infraJobExecutionDao;
private final Duration ttl;
public TaskHistoryWiper(InfraJobExecutionDao infraJobExecutionDao, Duration
ttl) {
this.infraJobExecutionDao = infraJobExecutionDao;
- if (ttl == null || ttl.compareTo(DEFAULT_TTL) < 0) {
- logger.info("The ttl value ({}) less than the minimum required. Using
the default ({}) instead", ttl, DEFAULT_TTL);
- this.ttl = DEFAULT_TTL;
+ if (ttl == null || ttl.compareTo(MINIMUM_TTL) < 0) {
+ logger.info("The ttl value ({}) less than the minimum required. Using
the minimum ({}) instead", ttl, MINIMUM_TTL);
+ this.ttl = MINIMUM_TTL;
}
else {
this.ttl = ttl;
@@ -49,7 +50,7 @@ public class TaskHistoryWiper implements Tasklet {
}
@Override
- public RepeatStatus execute(StepContribution contribution, ChunkContext
chunkContext) {
+ public RepeatStatus execute(@NonNull StepContribution contribution, @NonNull
ChunkContext chunkContext) {
infraJobExecutionDao.deleteJobExecutions(OffsetDateTime.now().minus(ttl));
return RepeatStatus.FINISHED;
}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/deleting/DocumentWiperTasklet.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/deleting/DocumentWiperTasklet.java
index cae64f4..9bde32a 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/deleting/DocumentWiperTasklet.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/job/deleting/DocumentWiperTasklet.java
@@ -26,6 +26,7 @@ import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
+import org.springframework.lang.NonNull;
public class DocumentWiperTasklet extends SolrDAOBase implements Tasklet {
private final DeletingProperties parameters;
@@ -36,7 +37,7 @@ public class DocumentWiperTasklet extends SolrDAOBase
implements Tasklet {
}
@Override
- public RepeatStatus execute(StepContribution contribution, ChunkContext
chunkContext) {
+ public RepeatStatus execute(@NonNull StepContribution contribution, @NonNull
ChunkContext chunkContext) {
delete(String.format("%s:[%s TO %s]",
parameters.getFilterField(),
getValue(parameters.getStart()),
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/DurationConverter.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/json/OffsetDateTimeToStringConverter.java
similarity index 60%
rename from
ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/DurationConverter.java
rename to
ambari-infra-manager/src/main/java/org/apache/ambari/infra/json/OffsetDateTimeToStringConverter.java
index 93b4794..25bdf19 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/DurationConverter.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/json/OffsetDateTimeToStringConverter.java
@@ -16,23 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.ambari.infra.conf;
+package org.apache.ambari.infra.json;
-import static
org.apache.ambari.infra.json.StringToDurationConverter.toDuration;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
-import java.time.Duration;
+import com.fasterxml.jackson.databind.util.StdConverter;
-import javax.annotation.Nullable;
-import javax.inject.Named;
+public class OffsetDateTimeToStringConverter extends
StdConverter<OffsetDateTime, String> {
-import
org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
-import org.springframework.core.convert.converter.Converter;
-
-@Named
-@ConfigurationPropertiesBinding
-public class DurationConverter implements Converter<String, Duration> {
@Override
- public Duration convert(@Nullable String s) {
- return toDuration(s);
+ public String convert(OffsetDateTime value) {
+ return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value);
}
}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/json/StringToDurationConverter.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/json/StringToDurationConverter.java
index 2a385cf..4746048 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/json/StringToDurationConverter.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/json/StringToDurationConverter.java
@@ -20,11 +20,19 @@ package org.apache.ambari.infra.json;
import java.time.Duration;
+import javax.inject.Named;
+
+import
org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.lang.NonNull;
+
import com.fasterxml.jackson.databind.util.StdConverter;
-public class StringToDurationConverter extends StdConverter<String, Duration> {
+@Named
+@ConfigurationPropertiesBinding
+public class StringToDurationConverter extends StdConverter<String, Duration>
implements Converter<String, Duration> {
@Override
- public Duration convert(String value) {
+ public Duration convert(@NonNull String value) {
return toDuration(value);
}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/json/StringToFsPermissionConverter.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/json/StringToFsPermissionConverter.java
index 70e4902..e271346 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/json/StringToFsPermissionConverter.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/json/StringToFsPermissionConverter.java
@@ -20,13 +20,20 @@ package org.apache.ambari.infra.json;
import static org.apache.commons.lang.StringUtils.isBlank;
+import javax.inject.Named;
+
import org.apache.hadoop.fs.permission.FsPermission;
+import
org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.lang.NonNull;
import com.fasterxml.jackson.databind.util.StdConverter;
-public class StringToFsPermissionConverter extends StdConverter<String,
FsPermission> {
+@Named
+@ConfigurationPropertiesBinding
+public class StringToFsPermissionConverter extends StdConverter<String,
FsPermission> implements Converter<String, FsPermission> {
@Override
- public FsPermission convert(String value) {
+ public FsPermission convert(@NonNull String value) {
return toFsPermission(value);
}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/manager/JobManager.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/manager/JobManager.java
index 86ffc1a..7886452 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/manager/JobManager.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/manager/JobManager.java
@@ -18,6 +18,8 @@
*/
package org.apache.ambari.infra.manager;
+import static java.util.Collections.unmodifiableList;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
@@ -26,13 +28,11 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.TimeZone;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.ambari.infra.model.ExecutionContextResponse;
-import org.apache.ambari.infra.model.JobDetailsResponse;
import org.apache.ambari.infra.model.JobExecutionDetailsResponse;
import org.apache.ambari.infra.model.JobExecutionInfoResponse;
import org.apache.ambari.infra.model.JobInstanceDetailsResponse;
@@ -78,8 +78,6 @@ public class JobManager implements Jobs {
@Inject
private JobExplorer jobExplorer;
- private TimeZone timeZone = TimeZone.getDefault();
-
public Set<String> getAllJobNames() {
return jobOperator.getJobNames();
}
@@ -97,7 +95,7 @@ public class JobManager implements Jobs {
if (!running.isEmpty())
throw new JobExecutionAlreadyRunningException("An instance of this job
is already active: "+jobName);
- return new JobExecutionInfoResponse(jobService.launch(jobName,
jobParameters), timeZone);
+ return new JobExecutionInfoResponse(jobService.launch(jobName,
jobParameters));
}
@Override
@@ -143,10 +141,10 @@ public class JobManager implements Jobs {
JobExecution jobExecution = jobService.getJobExecution(jobExecutionId);
List<StepExecutionInfoResponse> stepExecutionInfoList = new ArrayList<>();
for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
- stepExecutionInfoList.add(new StepExecutionInfoResponse(stepExecution,
timeZone));
+ stepExecutionInfoList.add(new StepExecutionInfoResponse(stepExecution));
}
-
stepExecutionInfoList.sort(Comparator.comparing(StepExecutionInfoResponse::getId));
- return new JobExecutionDetailsResponse(new
JobExecutionInfoResponse(jobExecution, timeZone), stepExecutionInfoList);
+
stepExecutionInfoList.sort(Comparator.comparing(StepExecutionInfoResponse::getStepExecutionId));
+ return new JobExecutionDetailsResponse(new
JobExecutionInfoResponse(jobExecution), stepExecutionInfoList);
}
/**
@@ -163,7 +161,7 @@ public class JobManager implements Jobs {
throw new UnsupportedOperationException("Unsupported operaration");
}
logger.info("Job {} was marked {}",
jobExecution.getJobInstance().getJobName(), operation.name());
- return new JobExecutionInfoResponse(jobExecution, timeZone);
+ return new JobExecutionInfoResponse(jobExecution);
}
/**
@@ -188,7 +186,7 @@ public class JobManager implements Jobs {
Collection<JobExecution> jobExecutions =
jobService.getJobExecutionsForJobInstance(jobName, jobInstanceId);
JobExecution jobExecution = jobExecutions.iterator().next();
Long jobExecutionId = jobExecution.getId();
- return new JobExecutionInfoResponse(jobService.restart(jobExecutionId),
timeZone);
+ return new JobExecutionInfoResponse(jobService.restart(jobExecutionId));
} else {
throw new UnsupportedOperationException("Unsupported operation (try:
RESTART)");
}
@@ -223,7 +221,7 @@ public class JobManager implements Jobs {
JobInstance jobInstance = jobService.getJobInstance(jobInstanceId);
Collection<JobExecution> jobExecutions =
jobService.getJobExecutionsForJobInstance(jobName, jobInstance.getInstanceId());
for (JobExecution jobExecution : jobExecutions) {
- result.add(new JobExecutionInfoResponse(jobExecution, timeZone));
+ result.add(new JobExecutionInfoResponse(jobExecution));
}
return result;
}
@@ -231,25 +229,26 @@ public class JobManager implements Jobs {
/**
* Get job details for a specific job. (paged)
*/
- public JobDetailsResponse getJobDetails(String jobName, int page, int size)
throws NoSuchJobException {
+ public List<JobInstanceDetailsResponse> getJobDetails(String jobName, int
page, int size) throws NoSuchJobException {
List<JobInstanceDetailsResponse> jobInstanceResponses =
Lists.newArrayList();
Collection<JobInstance> jobInstances =
jobService.listJobInstances(jobName, page, size);
- int count = jobService.countJobExecutionsForJob(jobName);
boolean launchable = jobService.isLaunchable(jobName);
- boolean isIncrementable = jobService.isIncrementable(jobName);
+ boolean incrementable = jobService.isIncrementable(jobName);
for (JobInstance jobInstance: jobInstances) {
- List<JobExecutionInfoResponse> executionInfos = Lists.newArrayList();
+ List<JobExecutionInfoResponse> executionInfoResponses =
Lists.newArrayList();
Collection<JobExecution> jobExecutions =
jobService.getJobExecutionsForJobInstance(jobName, jobInstance.getId());
if (jobExecutions != null) {
for (JobExecution jobExecution : jobExecutions) {
- executionInfos.add(new JobExecutionInfoResponse(jobExecution,
timeZone));
+ executionInfoResponses.add(new
JobExecutionInfoResponse(jobExecution));
}
}
- jobInstanceResponses.add(new JobInstanceDetailsResponse(jobInstance,
executionInfos));
+ jobInstanceResponses.add(new JobInstanceDetailsResponse(
+ new JobInfo(jobName, executionInfoResponses.size(),
jobInstance.getInstanceId(), launchable, incrementable),
+ executionInfoResponses));
}
- return new JobDetailsResponse(new JobInfo(jobName, count, launchable,
isIncrementable), jobInstanceResponses);
+ return unmodifiableList(jobInstanceResponses);
}
/**
@@ -257,7 +256,7 @@ public class JobManager implements Jobs {
*/
public StepExecutionInfoResponse getStepExecution(Long jobExecutionId, Long
stepExecutionId) throws NoSuchStepExecutionException,
NoSuchJobExecutionException {
StepExecution stepExecution = jobService.getStepExecution(jobExecutionId,
stepExecutionId);
- return new StepExecutionInfoResponse(stepExecution, timeZone);
+ return new StepExecutionInfoResponse(stepExecution);
}
/**
@@ -277,7 +276,7 @@ public class JobManager implements Jobs {
*/
public StepExecutionProgressResponse getStepExecutionProgress(Long
jobExecutionId, Long stepExecutionId) throws NoSuchStepExecutionException,
NoSuchJobExecutionException {
StepExecution stepExecution = jobService.getStepExecution(jobExecutionId,
stepExecutionId);
- StepExecutionInfoResponse stepExecutionInfoResponse = new
StepExecutionInfoResponse(stepExecution, timeZone);
+ StepExecutionInfoResponse stepExecutionInfoResponse = new
StepExecutionInfoResponse(stepExecution);
String stepName = stepExecution.getStepName();
if (stepName.contains(":partition")) {
stepName = stepName.replaceAll("(:partition).*", "$1*");
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/json/StringToDurationConverter.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/DateUtil.java
similarity index 66%
copy from
ambari-infra-manager/src/main/java/org/apache/ambari/infra/json/StringToDurationConverter.java
copy to
ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/DateUtil.java
index 2a385cf..810a95b 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/json/StringToDurationConverter.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/DateUtil.java
@@ -16,19 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.ambari.infra.json;
+package org.apache.ambari.infra.model;
-import java.time.Duration;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.util.Date;
-import com.fasterxml.jackson.databind.util.StdConverter;
-
-public class StringToDurationConverter extends StdConverter<String, Duration> {
- @Override
- public Duration convert(String value) {
- return toDuration(value);
- }
-
- public static Duration toDuration(String value) {
- return value == null ? null : Duration.parse(value);
+public class DateUtil {
+ public static OffsetDateTime toOffsetDateTime(Date date) {
+ if (date == null)
+ return null;
+ return date.toInstant().atOffset(ZoneOffset.UTC);
}
}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/ExecutionContextResponse.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/ExecutionContextResponse.java
index 2d46c54..0eb1a16 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/ExecutionContextResponse.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/ExecutionContextResponse.java
@@ -18,6 +18,8 @@
*/
package org.apache.ambari.infra.model;
+import static java.util.Collections.unmodifiableMap;
+
import java.util.Map;
public class ExecutionContextResponse {
@@ -27,7 +29,7 @@ public class ExecutionContextResponse {
public ExecutionContextResponse(Long jobExecutionId, Map<String, Object>
executionContextMap) {
this.jobExecutionId = jobExecutionId;
- this.executionContextMap = executionContextMap;
+ this.executionContextMap = unmodifiableMap(executionContextMap);
}
public Long getJobExecutionId() {
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/ExecutionContextResponse.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/ISO8601DateFormatter.java
similarity index 52%
copy from
ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/ExecutionContextResponse.java
copy to
ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/ISO8601DateFormatter.java
index 2d46c54..5f945b6 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/ExecutionContextResponse.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/ISO8601DateFormatter.java
@@ -6,9 +6,9 @@
* 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
@@ -18,23 +18,24 @@
*/
package org.apache.ambari.infra.model;
-import java.util.Map;
+import java.text.DateFormat;
+import java.text.FieldPosition;
+import java.text.ParsePosition;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Date;
-public class ExecutionContextResponse {
-
- private final Long jobExecutionId;
- private final Map<String, Object> executionContextMap;
-
- public ExecutionContextResponse(Long jobExecutionId, Map<String, Object>
executionContextMap) {
- this.jobExecutionId = jobExecutionId;
- this.executionContextMap = executionContextMap;
- }
-
- public Long getJobExecutionId() {
- return jobExecutionId;
+public class ISO8601DateFormatter extends DateFormat {
+ @Override
+ public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition
fieldPosition) {
+
toAppendTo.append(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(DateUtil.toOffsetDateTime(date)));
+ return toAppendTo;
}
- public Map<String, Object> getExecutionContextMap() {
- return executionContextMap;
+ @Override
+ public Date parse(String source, ParsePosition pos) {
+ OffsetDateTime offsetDateTime = OffsetDateTime.parse(source,
DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+ pos.setIndex(pos.getIndex() + source.length());
+ return Date.from(offsetDateTime.toInstant());
}
}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobDetailsResponse.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobDetailsResponse.java
deleted file mode 100644
index cd34fef..0000000
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobDetailsResponse.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.infra.model;
-
-import org.springframework.batch.admin.web.JobInfo;
-
-import java.util.List;
-
-public class JobDetailsResponse {
-
- private JobInfo jobInfo;
- private List<JobInstanceDetailsResponse> jobInstanceDetailsResponseList;
-
- public JobDetailsResponse() {
- }
-
- public JobDetailsResponse(JobInfo jobInfo, List<JobInstanceDetailsResponse>
jobInstanceDetailsResponseList) {
- this.jobInfo = jobInfo;
- this.jobInstanceDetailsResponseList = jobInstanceDetailsResponseList;
- }
-
- public JobInfo getJobInfo() {
- return jobInfo;
- }
-
- public void setJobInfo(JobInfo jobInfo) {
- this.jobInfo = jobInfo;
- }
-
- public List<JobInstanceDetailsResponse> getJobInstanceDetailsResponseList() {
- return jobInstanceDetailsResponseList;
- }
-
- public void
setJobInstanceDetailsResponseList(List<JobInstanceDetailsResponse>
jobInstanceDetailsResponseList) {
- this.jobInstanceDetailsResponseList = jobInstanceDetailsResponseList;
- }
-}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionDetailsResponse.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionDetailsResponse.java
index 695b57f..9e19344 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionDetailsResponse.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionDetailsResponse.java
@@ -18,32 +18,30 @@
*/
package org.apache.ambari.infra.model;
+import static java.util.Collections.unmodifiableList;
+
import java.util.List;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
public class JobExecutionDetailsResponse {
- private JobExecutionInfoResponse jobExecutionInfoResponse;
+ @JsonProperty("jobExecution")
+ private final JobExecutionInfoResponse jobExecutionInfoResponse;
- private List<StepExecutionInfoResponse> stepExecutionInfoList;
+ @JsonProperty("stepExecutionList")
+ private final List<StepExecutionInfoResponse> stepExecutionInfoList;
public JobExecutionDetailsResponse(JobExecutionInfoResponse
jobExecutionInfoResponse, List<StepExecutionInfoResponse>
stepExecutionInfoList) {
this.jobExecutionInfoResponse = jobExecutionInfoResponse;
- this.stepExecutionInfoList = stepExecutionInfoList;
+ this.stepExecutionInfoList = unmodifiableList(stepExecutionInfoList);
}
public JobExecutionInfoResponse getJobExecutionInfoResponse() {
return jobExecutionInfoResponse;
}
- public void setJobExecutionInfoResponse(JobExecutionInfoResponse
jobExecutionInfoResponse) {
- this.jobExecutionInfoResponse = jobExecutionInfoResponse;
- }
-
public List<StepExecutionInfoResponse> getStepExecutionInfoList() {
return stepExecutionInfoList;
}
-
- public void setStepExecutionInfoList(List<StepExecutionInfoResponse>
stepExecutionInfoList) {
- this.stepExecutionInfoList = stepExecutionInfoList;
- }
}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionInfoResponse.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionInfoResponse.java
index a7e4a4f..1034eb8 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionInfoResponse.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionInfoResponse.java
@@ -18,111 +18,122 @@
*/
package org.apache.ambari.infra.model;
-import org.apache.ambari.infra.model.wrapper.JobExecutionData;
-import org.springframework.batch.admin.web.JobParametersExtractor;
+import static java.util.Collections.unmodifiableList;
+import static org.apache.ambari.infra.model.DateUtil.toOffsetDateTime;
+
+import java.time.Duration;
+import java.time.OffsetDateTime;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.ambari.infra.json.DurationToStringConverter;
+import org.apache.ambari.infra.json.OffsetDateTimeToStringConverter;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.converter.DefaultJobParametersConverter;
-import org.springframework.batch.core.converter.JobParametersConverter;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Properties;
-import java.util.TimeZone;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+import io.swagger.annotations.ApiModelProperty;
public class JobExecutionInfoResponse {
- private Long id;
- private int stepExecutionCount;
- private Long jobId;
- private String jobName;
- private String startDate = "";
- private String startTime = "";
- private String duration = "";
- private JobExecutionData jobExecutionData;
- private Properties jobParameters;
- private String jobParametersString;
- private boolean restartable = false;
- private boolean abandonable = false;
- private boolean stoppable = false;
- private final TimeZone timeZone;
-
-
- public JobExecutionInfoResponse(JobExecution jobExecution, TimeZone
timeZone) {
- JobParametersConverter converter = new DefaultJobParametersConverter();
- this.jobExecutionData = new JobExecutionData(jobExecution);
- this.timeZone = timeZone;
- this.id = jobExecutionData.getId();
- this.jobId = jobExecutionData.getJobId();
- this.stepExecutionCount = jobExecutionData.getStepExecutions().size();
- this.jobParameters =
converter.getProperties(jobExecutionData.getJobParameters());
- this.jobParametersString = (new
JobParametersExtractor()).fromJobParameters(jobExecutionData.getJobParameters());
- JobInstance jobInstance = jobExecutionData.getJobInstance();
+ private static final DefaultJobParametersConverter
DEFAULT_JOB_PARAMETERS_CONVERTER = new DefaultJobParametersConverter();
+
+ static {
+ DEFAULT_JOB_PARAMETERS_CONVERTER.setDateFormat(new ISO8601DateFormatter());
+ }
+
+ private final Long jobExecutionId;
+ private final Long jobInstanceId;
+ private final String jobName;
+ @JsonSerialize(converter = OffsetDateTimeToStringConverter.class)
+ private final OffsetDateTime creationTime;
+ @JsonSerialize(converter = OffsetDateTimeToStringConverter.class)
+ private final OffsetDateTime startTime;
+ @JsonSerialize(converter = OffsetDateTimeToStringConverter.class)
+ private final OffsetDateTime lastUpdatedTime;
+ @JsonSerialize(converter = OffsetDateTimeToStringConverter.class)
+ private final OffsetDateTime endTime;
+ @JsonSerialize(converter = DurationToStringConverter.class)
+ @ApiModelProperty(dataType = "java.lang.String", example = "PT5.311S")
+ private final Duration duration;
+ private final Properties jobParameters;
+ private final BatchStatus batchStatus;
+ @ApiModelProperty(example = "COMPLETED", allowableValues = "UNKNOWN,
EXECUTING, COMPLETED, NOOP, FAILED, STOPPED")
+ private final String exitCode;
+ private final String exitDescription;
+ private final boolean restartable;
+ private final boolean abandonable;
+ private final boolean stoppable;
+ private final List<Throwable> failureExceptions;
+ private final String jobConfigurationName;
+
+
+ public JobExecutionInfoResponse(JobExecution jobExecution) {
+ this.jobExecutionId = jobExecution.getId();
+ this.jobInstanceId = jobExecution.getJobId();
+ this.jobParameters =
DEFAULT_JOB_PARAMETERS_CONVERTER.getProperties(jobExecution.getJobParameters());
+ this.creationTime = toOffsetDateTime(jobExecution.getCreateTime());
+ this.startTime = toOffsetDateTime(jobExecution.getStartTime());
+ this.lastUpdatedTime = toOffsetDateTime(jobExecution.getLastUpdated());
+ this.endTime = toOffsetDateTime(jobExecution.getEndTime());
+ JobInstance jobInstance = jobExecution.getJobInstance();
+ this.batchStatus = jobExecution.getStatus();
+ this.restartable = batchStatus.isGreaterThan(BatchStatus.STOPPING) &&
batchStatus.isLessThan(BatchStatus.ABANDONED);
+ this.abandonable = batchStatus.isGreaterThan(BatchStatus.STARTED) &&
batchStatus != BatchStatus.ABANDONED;
+ this.stoppable = batchStatus.isLessThan(BatchStatus.STOPPING);
+
+ if (jobExecution.getExitStatus() != null) {
+ this.exitCode = jobExecution.getExitStatus().getExitCode();
+ this.exitDescription = jobExecution.getExitStatus().getExitDescription();
+ }
+ else {
+ this.exitCode = null;
+ this.exitDescription = null;
+ }
+
if(jobInstance != null) {
this.jobName = jobInstance.getJobName();
- BatchStatus endTime = jobExecutionData.getStatus();
- this.restartable = endTime.isGreaterThan(BatchStatus.STOPPING) &&
endTime.isLessThan(BatchStatus.ABANDONED);
- this.abandonable = endTime.isGreaterThan(BatchStatus.STARTED) && endTime
!= BatchStatus.ABANDONED;
- this.stoppable = endTime.isLessThan(BatchStatus.STOPPING);
} else {
this.jobName = "?";
}
- SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
- SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
- SimpleDateFormat durationFormat = new SimpleDateFormat("HH:mm:ss");
-
- durationFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
- timeFormat.setTimeZone(timeZone);
- dateFormat.setTimeZone(timeZone);
- if(jobExecutionData.getStartTime() != null) {
- this.startDate = dateFormat.format(jobExecutionData.getStartTime());
- this.startTime = timeFormat.format(jobExecutionData.getStartTime());
- Date endTime1 = jobExecutionData.getEndTime() != null?
jobExecutionData.getEndTime():new Date();
- this.duration = durationFormat.format(new Date(endTime1.getTime() -
jobExecutionData.getStartTime().getTime()));
+ if(startTime != null && endTime != null) {
+ this.duration = Duration.between(startTime, endTime);
+ }
+ else {
+ this.duration = null;
}
- }
- public Long getId() {
- return id;
+ this.failureExceptions =
unmodifiableList(jobExecution.getFailureExceptions());
+ this.jobConfigurationName = jobExecution.getJobConfigurationName();
}
- public int getStepExecutionCount() {
- return stepExecutionCount;
+ public Long getJobExecutionId() {
+ return jobExecutionId;
}
- public Long getJobId() {
- return jobId;
+ public Long getJobInstanceId() {
+ return jobInstanceId;
}
public String getJobName() {
return jobName;
}
- public String getStartDate() {
- return startDate;
- }
-
- public String getStartTime() {
+ public OffsetDateTime getStartTime() {
return startTime;
}
- public String getDuration() {
+ public Duration getDuration() {
return duration;
}
- public JobExecutionData getJobExecutionData() {
- return jobExecutionData;
- }
-
public Properties getJobParameters() {
return jobParameters;
}
- public String getJobParametersString() {
- return jobParametersString;
- }
-
public boolean isRestartable() {
return restartable;
}
@@ -135,7 +146,35 @@ public class JobExecutionInfoResponse {
return stoppable;
}
- public TimeZone getTimeZone() {
- return timeZone;
+ public BatchStatus getBatchStatus() {
+ return batchStatus;
+ }
+
+ public OffsetDateTime getCreationTime() {
+ return creationTime;
+ }
+
+ public OffsetDateTime getEndTime() {
+ return endTime;
+ }
+
+ public OffsetDateTime getLastUpdatedTime() {
+ return lastUpdatedTime;
+ }
+
+ public String getExitCode() {
+ return exitCode;
+ }
+
+ public String getExitDescription() {
+ return exitDescription;
+ }
+
+ public List<Throwable> getFailureExceptions() {
+ return this.failureExceptions;
+ }
+
+ public String getJobConfigurationName() {
+ return this.jobConfigurationName;
}
}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionRestartRequest.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionRestartRequest.java
index 3eab25f..fe36c5b 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionRestartRequest.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionRestartRequest.java
@@ -22,6 +22,8 @@ import javax.validation.constraints.NotNull;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
+import io.swagger.annotations.ApiParam;
+
public class JobExecutionRestartRequest {
@PathParam("jobName")
@@ -34,6 +36,7 @@ public class JobExecutionRestartRequest {
@QueryParam("operation")
@NotNull
+ @ApiParam(required = true)
private JobOperationParams.JobRestartOperationParam operation;
public String getJobName() {
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionStopRequest.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionStopRequest.java
index b176f12..510e694 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionStopRequest.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionStopRequest.java
@@ -22,6 +22,8 @@ import javax.validation.constraints.NotNull;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
+import io.swagger.annotations.ApiParam;
+
public class JobExecutionStopRequest {
@PathParam("jobExecutionId")
@@ -30,6 +32,7 @@ public class JobExecutionStopRequest {
@QueryParam("operation")
@NotNull
+ @ApiParam(required = true)
private JobOperationParams.JobStopOrAbandonOperationParam operation;
public Long getJobExecutionId() {
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceDetailsResponse.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceDetailsResponse.java
index af88654..9bb7994 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceDetailsResponse.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceDetailsResponse.java
@@ -18,37 +18,31 @@
*/
package org.apache.ambari.infra.model;
-import org.springframework.batch.core.JobInstance;
+import static java.util.Collections.unmodifiableList;
import java.util.List;
-public class JobInstanceDetailsResponse {
+import org.springframework.batch.admin.web.JobInfo;
- private JobInstance jobInstance;
+import com.fasterxml.jackson.annotation.JsonProperty;
- private List<JobExecutionInfoResponse> jobExecutionInfoResponseList;
- public JobInstanceDetailsResponse() {
- }
+public class JobInstanceDetailsResponse {
- public JobInstanceDetailsResponse(JobInstance jobInstance,
List<JobExecutionInfoResponse> jobExecutionInfoResponseList) {
- this.jobInstance = jobInstance;
- this.jobExecutionInfoResponseList = jobExecutionInfoResponseList;
- }
+ private final JobInfo jobInfo;
+ @JsonProperty("jobExecutionList")
+ private final List<JobExecutionInfoResponse> jobExecutionInfoResponseList;
- public JobInstance getJobInstance() {
- return jobInstance;
+ public JobInstanceDetailsResponse(JobInfo jobInfo,
List<JobExecutionInfoResponse> jobExecutionInfoResponseList) {
+ this.jobInfo = jobInfo;
+ this.jobExecutionInfoResponseList =
unmodifiableList(jobExecutionInfoResponseList);
}
- public void setJobInstance(JobInstance jobInstance) {
- this.jobInstance = jobInstance;
+ public JobInfo getJobInfo() {
+ return jobInfo;
}
public List<JobExecutionInfoResponse> getJobExecutionInfoResponseList() {
return jobExecutionInfoResponseList;
}
-
- public void setJobExecutionInfoResponseList(List<JobExecutionInfoResponse>
jobExecutionInfoResponseList) {
- this.jobExecutionInfoResponseList = jobExecutionInfoResponseList;
- }
}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceStartRequest.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceStartRequest.java
index 905a4fa..5c760f6 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceStartRequest.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceStartRequest.java
@@ -22,14 +22,17 @@ import javax.validation.constraints.NotNull;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
+import io.swagger.annotations.ApiParam;
+
public class JobInstanceStartRequest {
@PathParam("jobName")
@NotNull
+ @ApiParam(required = true)
private String jobName;
@QueryParam("params")
- String params;
+ private String params;
public String getJobName() {
return jobName;
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionContextResponse.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionContextResponse.java
index 0e67a87..9ce56af 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionContextResponse.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionContextResponse.java
@@ -18,23 +18,22 @@
*/
package org.apache.ambari.infra.model;
+import static java.util.Collections.unmodifiableMap;
+
import java.util.Map;
public class StepExecutionContextResponse {
- private Map<String, Object> executionContextMap;
-
- private Long jobExecutionId;
+ private final Map<String, Object> executionContextMap;
- private Long stepExecutionId;
+ private final Long jobExecutionId;
- private String stepName;
+ private final Long stepExecutionId;
- public StepExecutionContextResponse() {
- }
+ private final String stepName;
public StepExecutionContextResponse(Map<String, Object> executionContextMap,
Long jobExecutionId, Long stepExecutionId, String stepName) {
- this.executionContextMap = executionContextMap;
+ this.executionContextMap = unmodifiableMap(executionContextMap);
this.jobExecutionId = jobExecutionId;
this.stepExecutionId = stepExecutionId;
this.stepName = stepName;
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionInfoResponse.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionInfoResponse.java
index ed04767..011eaea 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionInfoResponse.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionInfoResponse.java
@@ -18,98 +18,101 @@
*/
package org.apache.ambari.infra.model;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import org.apache.ambari.infra.model.wrapper.StepExecutionData;
-import org.springframework.batch.core.JobExecution;
+import static org.apache.ambari.infra.model.DateUtil.toOffsetDateTime;
+
+import java.time.Duration;
+import java.time.OffsetDateTime;
+
+import org.apache.ambari.infra.json.DurationToStringConverter;
+import org.apache.ambari.infra.json.OffsetDateTimeToStringConverter;
+import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.StepExecution;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.TimeZone;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-public class StepExecutionInfoResponse {
- private Long id;
- private Long jobExecutionId;
- private String jobName;
- private String name;
- private String startDate = "-";
- private String startTime = "-";
- private String duration = "-";
- private StepExecutionData stepExecutionData;
- private long durationMillis;
-
- public StepExecutionInfoResponse(String jobName, Long jobExecutionId, String
name, TimeZone timeZone) {
- this.jobName = jobName;
- this.jobExecutionId = jobExecutionId;
- this.name = name;
- this.stepExecutionData = new StepExecutionData(new StepExecution(name, new
JobExecution(jobExecutionId)));
- }
+import io.swagger.annotations.ApiModelProperty;
- public StepExecutionInfoResponse(StepExecution stepExecution, TimeZone
timeZone) {
- this.stepExecutionData = new StepExecutionData(stepExecution);
- this.id = stepExecutionData.getId();
- this.name = stepExecutionData.getStepName();
- this.jobName = stepExecutionData.getJobExecution() != null &&
stepExecutionData.getJobExecution().getJobInstance() != null?
stepExecutionData.getJobExecution().getJobInstance().getJobName():"?";
- this.jobExecutionId = stepExecutionData.getJobExecutionId();
- SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
- SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
- SimpleDateFormat durationFormat = new SimpleDateFormat("HH:mm:ss");
-
- durationFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
- timeFormat.setTimeZone(timeZone);
- dateFormat.setTimeZone(timeZone);
- if(stepExecutionData.getStartTime() != null) {
- this.startDate = dateFormat.format(stepExecutionData.getStartTime());
- this.startTime = timeFormat.format(stepExecutionData.getStartTime());
- Date endTime = stepExecutionData.getEndTime() != null?
stepExecutionData.getEndTime():new Date();
- this.durationMillis = endTime.getTime() -
stepExecutionData.getStartTime().getTime();
- this.duration = durationFormat.format(new Date(this.durationMillis));
+public class StepExecutionInfoResponse {
+ private final Long stepExecutionId;
+ private final Long jobExecutionId;
+ private final String jobName;
+ private final String stepName;
+ @JsonSerialize(converter = OffsetDateTimeToStringConverter.class)
+ private final OffsetDateTime startTime;
+ @JsonSerialize(converter = OffsetDateTimeToStringConverter.class)
+ private final OffsetDateTime endTime;
+ @JsonSerialize(converter = DurationToStringConverter.class)
+ @ApiModelProperty(dataType = "java.lang.String", example = "PT5.311S")
+ private final Duration duration;
+ private final BatchStatus batchStatus;
+ @ApiModelProperty(example = "COMPLETED", allowableValues = "UNKNOWN,
EXECUTING, COMPLETED, NOOP, FAILED, STOPPED")
+ private final String exitCode;
+ private final String exitDescription;
+
+
+ public StepExecutionInfoResponse(StepExecution stepExecution) {
+ this.stepExecutionId = stepExecution.getId();
+ this.stepName = stepExecution.getStepName();
+ this.jobName = stepExecution.getJobExecution() != null &&
stepExecution.getJobExecution().getJobInstance() != null ?
stepExecution.getJobExecution().getJobInstance().getJobName() : "?";
+ this.jobExecutionId = stepExecution.getJobExecutionId();
+ this.startTime = toOffsetDateTime(stepExecution.getStartTime());
+ this.endTime = toOffsetDateTime(stepExecution.getEndTime());
+
+ if(this.startTime != null && this.endTime != null) {
+ this.duration = Duration.between(this.startTime, this.endTime);
+ }
+ else {
+ this.duration = null;
}
+ this.batchStatus = stepExecution.getStatus();
+ if (stepExecution.getExitStatus() != null) {
+ this.exitCode = stepExecution.getExitStatus().getExitCode();
+ this.exitDescription =
stepExecution.getExitStatus().getExitDescription();
+ }
+ else {
+ this.exitCode = null;
+ this.exitDescription = null;
+ }
}
- public Long getId() {
- return this.id;
+ public Long getStepExecutionId() {
+ return this.stepExecutionId;
}
public Long getJobExecutionId() {
return this.jobExecutionId;
}
- public String getName() {
- return this.name;
+ public String getStepName() {
+ return this.stepName;
}
public String getJobName() {
return this.jobName;
}
- public String getStartDate() {
- return this.startDate;
- }
-
- public String getStartTime() {
- return this.startTime;
+ public OffsetDateTime getStartTime() {
+ return startTime;
}
- public String getDuration() {
- return this.duration;
+ public OffsetDateTime getEndTime() {
+ return endTime;
}
- public long getDurationMillis() {
- return this.durationMillis;
+ public Duration getDuration() {
+ return duration;
}
- public String getStatus() {
- return this.id !=
null?this.stepExecutionData.getStatus().toString():"NONE";
+ public BatchStatus getBatchStatus() {
+ return batchStatus;
}
public String getExitCode() {
- return this.id !=
null?this.stepExecutionData.getExitStatus().getExitCode():"NONE";
+ return exitCode;
}
- @JsonIgnore
- public StepExecutionData getStepExecution() {
- return this.stepExecutionData;
+ public String getExitDescription() {
+ return exitDescription;
}
}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionProgressResponse.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionProgressResponse.java
index 26f9ed4..d2404e5 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionProgressResponse.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionProgressResponse.java
@@ -21,16 +21,16 @@ package org.apache.ambari.infra.model;
import org.springframework.batch.admin.history.StepExecutionHistory;
import org.springframework.batch.admin.web.StepExecutionProgress;
-public class StepExecutionProgressResponse {
+import com.fasterxml.jackson.annotation.JsonProperty;
- private StepExecutionProgress stepExecutionProgress;
+public class StepExecutionProgressResponse {
- private StepExecutionHistory stepExecutionHistory;
+ private final StepExecutionProgress stepExecutionProgress;
- private StepExecutionInfoResponse stepExecutionInfoResponse;
+ private final StepExecutionHistory stepExecutionHistory;
- public StepExecutionProgressResponse() {
- }
+ @JsonProperty("stepExecution")
+ private final StepExecutionInfoResponse stepExecutionInfoResponse;
public StepExecutionProgressResponse(StepExecutionProgress
stepExecutionProgress, StepExecutionHistory stepExecutionHistory,
StepExecutionInfoResponse
stepExecutionInfoResponse) {
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/wrapper/JobExecutionData.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/wrapper/JobExecutionData.java
deleted file mode 100644
index 28e262a..0000000
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/wrapper/JobExecutionData.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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.infra.model.wrapper;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.google.common.collect.Lists;
-import org.springframework.batch.core.BatchStatus;
-import org.springframework.batch.core.ExitStatus;
-import org.springframework.batch.core.JobExecution;
-import org.springframework.batch.core.JobInstance;
-import org.springframework.batch.core.JobParameters;
-import org.springframework.batch.core.StepExecution;
-import org.springframework.batch.item.ExecutionContext;
-
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-
-/**
- * Wrapper for #{{@link JobExecution}}
- */
-public class JobExecutionData {
-
- private JobExecution jobExecution;
-
- public JobExecutionData(JobExecution jobExecution) {
- this.jobExecution = jobExecution;
- }
-
- @JsonIgnore
- public JobExecution getJobExecution() {
- return jobExecution;
- }
-
- @JsonIgnore
- public Collection<StepExecution> getStepExecutions() {
- return jobExecution.getStepExecutions();
- }
-
- public JobParameters getJobParameters() {
- return jobExecution.getJobParameters();
- }
-
- public JobInstance getJobInstance() {
- return jobExecution.getJobInstance();
- }
-
- public Collection<StepExecutionData> getStepExecutionDataList() {
- List<StepExecutionData> stepExecutionDataList = Lists.newArrayList();
- Collection<StepExecution> stepExecutions = getStepExecutions();
- if (stepExecutions != null) {
- for (StepExecution stepExecution : stepExecutions) {
- stepExecutionDataList.add(new StepExecutionData(stepExecution));
- }
- }
- return stepExecutionDataList;
- }
-
- public BatchStatus getStatus() {
- return jobExecution.getStatus();
- }
-
- public Date getStartTime() {
- return jobExecution.getStartTime();
- }
-
- public Date getCreateTime() {
- return jobExecution.getCreateTime();
- }
-
- public Date getEndTime() {
- return jobExecution.getEndTime();
- }
-
- public Date getLastUpdated() {
- return jobExecution.getLastUpdated();
- }
-
- public ExitStatus getExitStatus() {
- return jobExecution.getExitStatus();
- }
-
- public ExecutionContext getExecutionContext() {
- return jobExecution.getExecutionContext();
- }
-
- public List<Throwable> getFailureExceptions() {
- return jobExecution.getFailureExceptions();
- }
-
- public String getJobConfigurationName() {
- return jobExecution.getJobConfigurationName();
- }
-
- public Long getId() {
- return jobExecution.getId();
- }
-
- public Long getJobId() {
- return jobExecution.getJobId();
- }
-}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/wrapper/StepExecutionData.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/wrapper/StepExecutionData.java
deleted file mode 100644
index 26552ae..0000000
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/wrapper/StepExecutionData.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.infra.model.wrapper;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import org.springframework.batch.core.BatchStatus;
-import org.springframework.batch.core.ExitStatus;
-import org.springframework.batch.core.JobExecution;
-import org.springframework.batch.core.StepExecution;
-import org.springframework.batch.item.ExecutionContext;
-
-import java.util.Date;
-import java.util.List;
-
-/**
- * Wrapper for #{{@link StepExecution}}
- */
-public class StepExecutionData {
-
- @JsonIgnore
- private final JobExecution jobExecution;
-
- @JsonIgnore
- private final StepExecution stepExecution;
-
-
- public StepExecutionData(StepExecution stepExecution) {
- this.stepExecution = stepExecution;
- this.jobExecution = stepExecution.getJobExecution();
- }
-
- @JsonIgnore
- public JobExecution getJobExecution() {
- return jobExecution;
- }
-
- @JsonIgnore
- public StepExecution getStepExecution() {
- return stepExecution;
- }
-
- public String getStepName() {
- return stepExecution.getStepName();
- }
-
- public int getReadCount() {
- return stepExecution.getReadCount();
- }
-
- public BatchStatus getStatus() {
- return stepExecution.getStatus();
- }
-
- public int getWriteCount() {
- return stepExecution.getWriteCount();
- }
-
- public int getCommitCount() {
- return stepExecution.getCommitCount();
- }
-
- public int getRollbackCount() {
- return stepExecution.getRollbackCount();
- }
-
- public int getReadSkipCount() {
- return stepExecution.getReadSkipCount();
- }
-
- public int getProcessSkipCount() {
- return stepExecution.getProcessSkipCount();
- }
-
- public Date getStartTime() {
- return stepExecution.getStartTime();
- }
-
- public int getWriteSkipCount() {
- return stepExecution.getWriteSkipCount();
- }
-
- public Date getEndTime() {
- return stepExecution.getEndTime();
- }
-
- public Date getLastUpdated() {
- return stepExecution.getLastUpdated();
- }
-
- public ExecutionContext getExecutionContext() {
- return stepExecution.getExecutionContext();
- }
-
- public ExitStatus getExitStatus() {
- return stepExecution.getExitStatus();
- }
-
- public boolean isTerminateOnly() {
- return stepExecution.isTerminateOnly();
- }
-
- public int getFilterCount() {
- return stepExecution.getFilterCount();
- }
-
- public List<Throwable> getFailureExceptions() {
- return stepExecution.getFailureExceptions();
- }
-
- public Long getId() {
- return stepExecution.getId();
- }
-
- public Long getJobExecutionId() {
- return stepExecution.getJobExecutionId();
- }
-}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/ApiDocResource.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/ApiDocResource.java
deleted file mode 100644
index 18dfdd9..0000000
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/ApiDocResource.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.infra.rest;
-
-import io.swagger.annotations.ApiOperation;
-import org.apache.ambari.infra.doc.InfraManagerApiDocStorage;
-import org.springframework.context.annotation.Scope;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-@Path("swagger.{type:json|yaml}")
-@Named
-@Scope("request")
-public class ApiDocResource {
-
- @Inject
- private InfraManagerApiDocStorage infraManagerApiDocStorage;
-
- @GET
- @Produces({MediaType.APPLICATION_JSON, "application/yaml"})
- @ApiOperation(value = "The swagger definition in either JSON or YAML",
hidden = true)
- public Response swaggerDefinitionResponse(@PathParam("type") String type) {
- Response response = Response.status(404).build();
- if (infraManagerApiDocStorage.getSwagger() != null) {
- if ("yaml".equalsIgnoreCase(type)) {
- response =
Response.ok().entity(infraManagerApiDocStorage.getSwaggerYaml()).type("application/yaml").build();
- } else {
- response =
Response.ok().entity(infraManagerApiDocStorage.getSwagger()).build();
- }
- }
- return response;
- }
-}
diff --git
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/JobResource.java
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/JobResource.java
index 43f7c41..f5de3c0 100644
---
a/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/JobResource.java
+++
b/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/JobResource.java
@@ -35,12 +35,12 @@ import javax.ws.rs.Produces;
import org.apache.ambari.infra.manager.JobManager;
import org.apache.ambari.infra.model.ExecutionContextResponse;
-import org.apache.ambari.infra.model.JobDetailsResponse;
import org.apache.ambari.infra.model.JobExecutionDetailsResponse;
import org.apache.ambari.infra.model.JobExecutionInfoResponse;
import org.apache.ambari.infra.model.JobExecutionRequest;
import org.apache.ambari.infra.model.JobExecutionRestartRequest;
import org.apache.ambari.infra.model.JobExecutionStopRequest;
+import org.apache.ambari.infra.model.JobInstanceDetailsResponse;
import org.apache.ambari.infra.model.JobInstanceStartRequest;
import org.apache.ambari.infra.model.JobRequest;
import org.apache.ambari.infra.model.PageRequest;
@@ -120,7 +120,7 @@ public class JobResource {
@Produces({"application/json"})
@Path("{jobName}/info")
@ApiOperation("Get job details by job name.")
- public JobDetailsResponse getJobDetails(@BeanParam @Valid JobRequest
jobRequest) throws NoSuchJobException {
+ public List<JobInstanceDetailsResponse> getJobDetails(@BeanParam @Valid
JobRequest jobRequest) throws NoSuchJobException {
return jobManager.getJobDetails(jobRequest.getJobName(),
jobRequest.getPage(), jobRequest.getSize());
}
@@ -136,7 +136,7 @@ public class JobResource {
@Produces({"application/json"})
@Path("/executions/{jobExecutionId}")
@ApiOperation("Get job and step details for job execution instance.")
- public JobExecutionDetailsResponse
getExectionInfo(@PathParam("jobExecutionId") @Valid Long jobExecutionId) throws
NoSuchJobExecutionException {
+ public JobExecutionDetailsResponse
getExecutionInfo(@PathParam("jobExecutionId") @Valid Long jobExecutionId)
throws NoSuchJobExecutionException {
return jobManager.getExecutionInfo(jobExecutionId);
}
@@ -169,8 +169,8 @@ public class JobResource {
@GET
@Produces({"application/json"})
@Path("/{jobName}/{jobInstanceId}/executions")
- @ApiOperation("Get execution for job instance.")
- public List<JobExecutionInfoResponse> getExecutionsForInstance(@BeanParam
@Valid JobExecutionRequest request) throws
+ @ApiOperation("Get execution of job instance.")
+ public List<JobExecutionInfoResponse> getExecutionsOfInstance(@BeanParam
@Valid JobExecutionRequest request) throws
NoSuchJobException, NoSuchJobInstanceException {
return jobManager.getExecutionsForJobInstance(request.getJobName(),
request.getJobInstanceId());
}
diff --git a/ambari-infra-manager/src/main/resources/infra-manager.properties
b/ambari-infra-manager/src/main/resources/infra-manager.properties
index 8133905..c3ec9d0 100644
--- a/ambari-infra-manager/src/main/resources/infra-manager.properties
+++ b/ambari-infra-manager/src/main/resources/infra-manager.properties
@@ -18,6 +18,7 @@ infra-manager.batch.db.init=false
infra-manager.batch.db.username=admin
infra-manager.batch.db.password=admin
infra-manager.server.data.folder=/tmp/ambariInfraManager
+infra-manager.admin-user.password=admin
# Archive Service Logs
infra-manager.jobs.solr_data_archiving.archive_service_logs.enabled=true
diff --git a/ambari-infra-manager/src/main/resources/swagger/swagger.html
b/ambari-infra-manager/src/main/resources/swagger/swagger.html
index b24dd25..69478fd 100644
--- a/ambari-infra-manager/src/main/resources/swagger/swagger.html
+++ b/ambari-infra-manager/src/main/resources/swagger/swagger.html
@@ -57,7 +57,7 @@
var urlPrefix = location.protocol +'//'+
location.hostname+(location.port ? ':'+location.port: '');
// Build a system
const ui = SwaggerUIBundle({
- url: urlPrefix + "/api/v1/swagger.yaml",
+ url: urlPrefix + "/swagger.yaml",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
diff --git
a/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/DocumentExporterTest.java
b/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/DocumentExporterTest.java
index d2e7b04..fe2b037 100644
---
a/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/DocumentExporterTest.java
+++
b/ambari-infra-manager/src/test/java/org/apache/ambari/infra/job/archive/DocumentExporterTest.java
@@ -36,8 +36,8 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.scope.context.StepContext;
@@ -56,6 +56,8 @@ public class DocumentExporterTest extends EasyMockSupport {
private static final Document DOCUMENT_3 = new Document(new HashMap<String,
Object>() {{
put("id", "3");
}});
+ private static final StepContribution ANY_STEP_CONTRIBUTION = new
StepContribution(new StepExecution("any", new JobExecution(1L)));
+
private DocumentExporter documentExporter;
@Mock
private ItemStreamReader<Document> reader;
@@ -74,8 +76,8 @@ public class DocumentExporterTest extends EasyMockSupport {
private static final Document DOCUMENT = new Document(new HashMap<String,
Object>() {{ put("id", "1"); }});
@Before
- public void setUp() throws Exception {
- chunkContext = chunkContext(BatchStatus.STARTED);
+ public void setUp() {
+ chunkContext = chunkContext(false);
documentExporter = documentExporter(2);
}
@@ -83,15 +85,16 @@ public class DocumentExporterTest extends EasyMockSupport {
return new DocumentExporter(reader, documentDestination, writeBlockSize,
jobContextRepository);
}
- private ChunkContext chunkContext(BatchStatus batchStatus) {
+ private ChunkContext chunkContext(boolean terminate) {
StepExecution stepExecution = new StepExecution("exportDoc", new
JobExecution(JOB_EXECUTION_ID));
stepExecution.setId(STEP_EXECUTION_ID);
- stepExecution.getJobExecution().setStatus(batchStatus);
+ if (terminate)
+ stepExecution.setTerminateOnly();
return new ChunkContext(new StepContext(stepExecution));
}
@After
- public void tearDown() throws Exception {
+ public void tearDown() {
verifyAll();
}
@@ -102,7 +105,7 @@ public class DocumentExporterTest extends EasyMockSupport {
reader.close(); expectLastCall();
replayAll();
- documentExporter.execute(null, chunkContext);
+ documentExporter.execute(ANY_STEP_CONTRIBUTION, chunkContext);
}
private ExecutionContext executionContext(ChunkContext chunkContext) {
@@ -120,7 +123,7 @@ public class DocumentExporterTest extends EasyMockSupport {
documentItemWriter.close(); expectLastCall();
replayAll();
- assertThat(documentExporter.execute(null, chunkContext),
is(RepeatStatus.FINISHED));
+ assertThat(documentExporter.execute(ANY_STEP_CONTRIBUTION, chunkContext),
is(RepeatStatus.FINISHED));
}
@Test
@@ -143,7 +146,7 @@ public class DocumentExporterTest extends EasyMockSupport {
documentItemWriter2.close(); expectLastCall();
replayAll();
- assertThat(documentExporter.execute(null, chunkContext),
is(RepeatStatus.FINISHED));
+ assertThat(documentExporter.execute(ANY_STEP_CONTRIBUTION, chunkContext),
is(RepeatStatus.FINISHED));
}
@Test(expected = IOException.class)
@@ -157,7 +160,7 @@ public class DocumentExporterTest extends EasyMockSupport {
reader.close(); expectLastCall();
replayAll();
- documentExporter.execute(null, chunkContext);
+ documentExporter.execute(ANY_STEP_CONTRIBUTION, chunkContext);
}
@Test(expected = UncheckedIOException.class)
@@ -170,12 +173,12 @@ public class DocumentExporterTest extends EasyMockSupport
{
reader.close(); expectLastCall();
replayAll();
- documentExporter.execute(null, chunkContext);
+ documentExporter.execute(ANY_STEP_CONTRIBUTION, chunkContext);
}
@Test
public void testStopAndRestartExportsAllDocuments() throws Exception {
- ChunkContext stoppingChunkContext = chunkContext(BatchStatus.STOPPING);
+ ChunkContext stoppingChunkContext = chunkContext(true);
DocumentExporter documentExporter = documentExporter(1);
reader.open(executionContext(chunkContext)); expectLastCall();
@@ -206,9 +209,9 @@ public class DocumentExporterTest extends EasyMockSupport {
reader.close(); expectLastCall();
replayAll();
- RepeatStatus repeatStatus = documentExporter.execute(null,
this.chunkContext);
+ RepeatStatus repeatStatus =
documentExporter.execute(ANY_STEP_CONTRIBUTION, this.chunkContext);
assertThat(repeatStatus, is(RepeatStatus.CONTINUABLE));
- repeatStatus = documentExporter.execute(null, this.chunkContext);
+ repeatStatus = documentExporter.execute(ANY_STEP_CONTRIBUTION,
this.chunkContext);
assertThat(repeatStatus, is(RepeatStatus.FINISHED));
}
}
\ No newline at end of file
diff --git
a/ambari-infra-manager/src/test/java/org/apache/ambari/infra/model/ISO8601DateFormatterTest.java
b/ambari-infra-manager/src/test/java/org/apache/ambari/infra/model/ISO8601DateFormatterTest.java
new file mode 100644
index 0000000..b2bb0e8
--- /dev/null
+++
b/ambari-infra-manager/src/test/java/org/apache/ambari/infra/model/ISO8601DateFormatterTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.infra.model;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+import java.text.ParseException;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.util.Date;
+
+import org.junit.Test;
+
+public class ISO8601DateFormatterTest {
+
+ @Test
+ public void testFormat() {
+ OffsetDateTime offsetDateTime = OffsetDateTime.of(
+ 2018, 11, 30,
+ 2, 30, 11, 0,
+ ZoneOffset.ofHoursMinutes(1, 30));
+ String text = new
ISO8601DateFormatter().format(Date.from(offsetDateTime.toInstant()));
+ assertThat(text, is("2018-11-30T01:00:11Z"));
+ }
+
+ @Test
+ public void testParse() throws ParseException {
+ Date now = new Date();
+ ISO8601DateFormatter iso8601DateFormatter = new ISO8601DateFormatter();
+ Date parsed = iso8601DateFormatter.parse(iso8601DateFormatter.format(now));
+ assertThat(parsed, is(now));
+ }
+}
\ No newline at end of file