/*
* 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.flink.runtime.webmonitor.handlers;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.router.Routed;
import org.apache.flink.api.common.time.Time;
import org.apache.flink.configuration.ConfigConstants;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.runtime.akka.AkkaUtils;
import org.apache.flink.runtime.blob.BlobKey;
import org.apache.flink.runtime.blob.VoidBlobStore;
import org.apache.flink.runtime.clusterframework.types.ResourceID;
import org.apache.flink.runtime.concurrent.CompletableFuture;
import org.apache.flink.runtime.concurrent.Executors;
import org.apache.flink.runtime.concurrent.impl.FlinkCompletableFuture;
import org.apache.flink.runtime.instance.ActorGateway;
import org.apache.flink.runtime.instance.Instance;
import org.apache.flink.runtime.instance.InstanceID;
import org.apache.flink.runtime.jobmanager.slots.TaskManagerGateway;
import org.apache.flink.runtime.messages.JobManagerMessages;
import org.apache.flink.runtime.webmonitor.JobManagerRetriever;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import scala.Option;
import scala.collection.JavaConverters;
import scala.concurrent.ExecutionContext$;
import scala.concurrent.ExecutionContextExecutor;
import scala.concurrent.Future$;
import scala.concurrent.duration.FiniteDuration;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.isA;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;
public class TaskManagerLogHandlerTest {
@Test
public void testGetPaths() {
TaskManagerLogHandler handlerLog = new TaskManagerLogHandler(
mock(JobManagerRetriever.class),
mock(ExecutionContextExecutor.class),
Future$.MODULE$.successful("/jm/address"),
AkkaUtils.getDefaultClientTimeout(),
TaskManagerLogHandler.FileMode.LOG,
new Configuration(),
false,
new VoidBlobStore());
String[] pathsLog = handlerLog.getPaths();
Assert.assertEquals(1, pathsLog.length);
Assert.assertEquals("/taskmanagers/:taskmanagerid/log", pathsLog[0]);
TaskManagerLogHandler handlerOut = new TaskManagerLogHandler(
mock(JobManagerRetriever.class),
mock(ExecutionContextExecutor.class),
Future$.MODULE$.successful("/jm/address"),
AkkaUtils.getDefaultClientTimeout(),
TaskManagerLogHandler.FileMode.STDOUT,
new Configuration(),
false,
new VoidBlobStore());
String[] pathsOut = handlerOut.getPaths();
Assert.assertEquals(1, pathsOut.length);
Assert.assertEquals("/taskmanagers/:taskmanagerid/stdout", pathsOut[0]);
}
@Test
public void testLogFetchingFailure() throws Exception {
// ========= setup TaskManager =================================================================================
InstanceID tmID = new InstanceID();
ResourceID tmRID = new ResourceID(tmID.toString());
TaskManagerGateway taskManagerGateway = mock(TaskManagerGateway.class);
when(taskManagerGateway.getAddress()).thenReturn("/tm/address");
Instance taskManager = mock(Instance.class);
when(taskManager.getId()).thenReturn(tmID);
when(taskManager.getTaskManagerID()).thenReturn(tmRID);
when(taskManager.getTaskManagerGateway()).thenReturn(taskManagerGateway);
CompletableFuture<BlobKey> future = new FlinkCompletableFuture<>();
future.completeExceptionally(new IOException("failure"));
when(taskManagerGateway.requestTaskManagerLog(any(Time.class))).thenReturn(future);
// ========= setup JobManager ==================================================================================
ActorGateway jobManagerGateway = mock(ActorGateway.class);
Object registeredTaskManagersAnswer = new JobManagerMessages.RegisteredTaskManagers(
JavaConverters.collectionAsScalaIterableConverter(Collections.singletonList(taskManager)).asScala());
when(jobManagerGateway.ask(isA(JobManagerMessages.RequestRegisteredTaskManagers$.class), any(FiniteDuration.class)))
.thenReturn(Future$.MODULE$.successful(registeredTaskManagersAnswer));
when(jobManagerGateway.ask(isA(JobManagerMessages.getRequestBlobManagerPort().getClass()), any(FiniteDuration.class)))
.thenReturn(Future$.MODULE$.successful((Object) 5));
when(jobManagerGateway.ask(isA(JobManagerMessages.RequestTaskManagerInstance.class), any(FiniteDuration.class)))
.thenReturn(Future$.MODULE$.successful((Object) new JobManagerMessages.TaskManagerInstance(Option.apply(taskManager))));
when(jobManagerGateway.path()).thenReturn("/jm/address");
JobManagerRetriever retriever = mock(JobManagerRetriever.class);
when(retriever.getJobManagerGatewayAndWebPort())
.thenReturn(Option.apply(new scala.Tuple2<ActorGateway, Integer>(jobManagerGateway, 0)));
TaskManagerLogHandler handler = new TaskManagerLogHandler(
retriever,
ExecutionContext$.MODULE$.fromExecutor(Executors.directExecutor()),
Future$.MODULE$.successful("/jm/address"),
AkkaUtils.getDefaultClientTimeout(),
TaskManagerLogHandler.FileMode.LOG,
new Configuration(),
false,
new VoidBlobStore());
final AtomicReference<String> exception = new AtomicReference<>();
ChannelHandlerContext ctx = mock(ChannelHandlerContext.class);
when(ctx.write(isA(ByteBuf.class))).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
ByteBuf data = invocationOnMock.getArgumentAt(0, ByteBuf.class);
exception.set(new String(data.array(), ConfigConstants.DEFAULT_CHARSET));
return null;
}
});
Map<String, String> pathParams = new HashMap<>();
pathParams.put(TaskManagersHandler.TASK_MANAGER_ID_KEY, tmID.toString());
Routed routed = mock(Routed.class);
when(routed.pathParams()).thenReturn(pathParams);
when(routed.request()).thenReturn(new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/taskmanagers/" + tmID + "/log"));
handler.respondAsLeader(ctx, routed, jobManagerGateway);
Assert.assertEquals("Fetching TaskManager log failed.", exception.get());
}
}