Skip to content

Commit

Permalink
BIGTOP-4163: Add quick links for service (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinw66 authored Jul 18, 2024
1 parent c4145ba commit a9aa638
Show file tree
Hide file tree
Showing 24 changed files with 252 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/
package org.apache.bigtop.manager.agent.utils;

import org.apache.bigtop.manager.common.utils.Environments;

import org.apache.commons.lang3.SystemUtils;

import java.io.File;
Expand All @@ -26,7 +28,7 @@ public class LogFileUtils {

public static String getLogFilePath(Long taskId) {
String baseDir;
if (SystemUtils.IS_OS_WINDOWS) {
if (Environments.isDevMode()) {
baseDir = SystemUtils.getUserDir().getPath();
} else {
File file = new File(LogFileUtils.class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package org.apache.bigtop.manager.common.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
Expand All @@ -34,6 +35,7 @@ public class JsonUtils {
static {
OBJECTMAPPER = new ObjectMapper();
OBJECTMAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
OBJECTMAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}

public static <T> void writeToFile(String fileName, T obj) {
Expand Down Expand Up @@ -73,6 +75,10 @@ public static <T> T readFromFile(File file, TypeReference<T> typeReference) {
}

public static <T> T readFromString(String json) {
if (json == null) {
return null;
}

try {
return OBJECTMAPPER.readValue(json, new TypeReference<>() {});
} catch (Exception e) {
Expand All @@ -81,6 +87,10 @@ public static <T> T readFromString(String json) {
}

public static <T> T readFromString(String json, TypeReference<T> typeReference) {
if (json == null) {
return null;
}

try {
return OBJECTMAPPER.readValue(json, typeReference);
} catch (Exception e) {
Expand All @@ -89,6 +99,10 @@ public static <T> T readFromString(String json, TypeReference<T> typeReference)
}

public static <T> T readFromString(String json, Class<T> clazz) {
if (json == null) {
return null;
}

try {
return OBJECTMAPPER.readValue(json, clazz);
} catch (Exception e) {
Expand All @@ -105,6 +119,10 @@ public static JsonNode readTree(String filename) {
}

public static <T> String writeAsString(T obj) {
if (obj == null) {
return null;
}

try {
return OBJECTMAPPER.writeValueAsString(obj);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ public class Component extends BaseEntity {
@Column(name = "category")
private String category;

@Column(name = "quick_link")
private String quickLink;

@ManyToOne
@JoinColumn(name = "service_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private Service service;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public class Service extends BaseEntity {
@Column(name = "service_group")
private String serviceGroup;

@Column(name = "required_service")
@Column(name = "required_services")
private String requiredServices;

@ManyToOne
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ public class SseController {
@Operation(summary = "get task log", description = "Get a task log")
@GetMapping("/tasks/{id}/log")
public SseEmitter log(@PathVariable Long id, @PathVariable Long clusterId) {
// Default timeout to 5 minutes
SseEmitter emitter = new SseEmitter(5 * 60 * 1000L);
// Default timeout to 30 minutes
SseEmitter emitter = new SseEmitter(30 * 60 * 1000L);

Flux<String> flux =
Flux.create(sink -> taskLogService.registerSink(id, sink), FluxSink.OverflowStrategy.BUFFER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ public class ComponentDTO {
private ScriptDTO commandScript;

private List<CustomCommandDTO> customCommands;

private QuickLinkDTO quickLink;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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
*
* https://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.bigtop.manager.server.model.dto;

import lombok.Data;

@Data
public class QuickLinkDTO {

private String displayName;

private String httpPortProperty;

private String httpPortDefault;

private String httpsPortProperty;

private String httpsPortDefault;
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public interface ComponentMapper {

@Mapping(target = "commandScript", source = "commandScript", qualifiedByName = "obj2Json")
@Mapping(target = "customCommands", source = "customCommands", qualifiedByName = "obj2Json")
@Mapping(target = "quickLink", source = "quickLink", qualifiedByName = "obj2Json")
@Mapping(target = "service", expression = "java(service)")
@Mapping(target = "cluster", expression = "java(cluster)")
Component fromDTO2Entity(ComponentDTO componentDTO, @Context Service service, @Context Cluster cluster);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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
*
* https://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.bigtop.manager.server.model.vo;

import lombok.Data;

@Data
public class QuickLinkVO {

private String displayName;

private String url;
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,6 @@ public class ServiceVO {
private Boolean isClient;

private Boolean isHealthy;

private List<QuickLinkVO> quickLinks;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,28 @@

import org.apache.bigtop.manager.common.constants.ComponentCategories;
import org.apache.bigtop.manager.common.enums.MaintainState;
import org.apache.bigtop.manager.common.utils.JsonUtils;
import org.apache.bigtop.manager.dao.entity.Cluster;
import org.apache.bigtop.manager.dao.entity.Component;
import org.apache.bigtop.manager.dao.entity.Host;
import org.apache.bigtop.manager.dao.entity.HostComponent;
import org.apache.bigtop.manager.dao.entity.Service;
import org.apache.bigtop.manager.dao.entity.ServiceConfig;
import org.apache.bigtop.manager.dao.entity.TypeConfig;
import org.apache.bigtop.manager.dao.repository.HostComponentRepository;
import org.apache.bigtop.manager.dao.repository.ServiceConfigRepository;
import org.apache.bigtop.manager.dao.repository.ServiceRepository;
import org.apache.bigtop.manager.server.model.dto.PropertyDTO;
import org.apache.bigtop.manager.server.model.dto.QuickLinkDTO;
import org.apache.bigtop.manager.server.model.dto.TypeConfigDTO;
import org.apache.bigtop.manager.server.model.mapper.ServiceMapper;
import org.apache.bigtop.manager.server.model.mapper.TypeConfigMapper;
import org.apache.bigtop.manager.server.model.vo.QuickLinkVO;
import org.apache.bigtop.manager.server.model.vo.ServiceVO;
import org.apache.bigtop.manager.server.service.ServiceService;

import org.apache.commons.lang3.StringUtils;

import lombok.extern.slf4j.Slf4j;

import jakarta.annotation.Resource;
Expand All @@ -46,6 +60,9 @@ public class ServiceServiceImpl implements ServiceService {
@Resource
private HostComponentRepository hostComponentRepository;

@Resource
private ServiceConfigRepository serviceConfigRepository;

@Override
public List<ServiceVO> list(Long clusterId) {
List<ServiceVO> res = new ArrayList<>();
Expand All @@ -58,11 +75,20 @@ public List<ServiceVO> list(Long clusterId) {
List<HostComponent> hostComponents = entry.getValue();
Service service = hostComponents.get(0).getComponent().getService();
ServiceVO serviceVO = ServiceMapper.INSTANCE.fromEntity2VO(service);
serviceVO.setQuickLinks(new ArrayList<>());

boolean isHealthy = true;
boolean isClient = true;
for (HostComponent hostComponent : hostComponents) {
String category = hostComponent.getComponent().getCategory();
Component component = hostComponent.getComponent();

String quickLink = component.getQuickLink();
if (StringUtils.isNotBlank(quickLink)) {
QuickLinkVO quickLinkVO = resolveQuickLink(hostComponent, quickLink);
serviceVO.getQuickLinks().add(quickLinkVO);
}

String category = component.getCategory();
if (!category.equalsIgnoreCase(ComponentCategories.CLIENT)) {
isClient = false;
}
Expand All @@ -88,4 +114,38 @@ public ServiceVO get(Long id) {
Service service = serviceRepository.findById(id).orElse(new Service());
return ServiceMapper.INSTANCE.fromEntity2VO(service);
}

private QuickLinkVO resolveQuickLink(HostComponent hostComponent, String quickLinkJson) {
QuickLinkVO quickLinkVO = new QuickLinkVO();

QuickLinkDTO quickLinkDTO = JsonUtils.readFromString(quickLinkJson, QuickLinkDTO.class);
quickLinkVO.setDisplayName(quickLinkDTO.getDisplayName());

Component component = hostComponent.getComponent();
Cluster cluster = component.getCluster();
Host host = hostComponent.getHost();
Service service = component.getService();
ServiceConfig serviceConfig =
serviceConfigRepository.findByClusterAndServiceAndSelectedIsTrue(cluster, service);
List<TypeConfig> typeConfigs = serviceConfig.getConfigs();

// Use HTTP for now, need to handle https in the future
for (TypeConfig typeConfig : typeConfigs) {
TypeConfigDTO typeConfigDTO = TypeConfigMapper.INSTANCE.fromEntity2DTO(typeConfig);
for (PropertyDTO propertyDTO : typeConfigDTO.getProperties()) {
if (propertyDTO.getName().equals(quickLinkDTO.getHttpPortProperty())) {
String port = propertyDTO.getValue().contains(":")
? propertyDTO.getValue().split(":")[1]
: propertyDTO.getValue();
String url = "http://" + host.getHostname() + ":" + port;
quickLinkVO.setUrl(url);
return quickLinkVO;
}
}
}

String url = "http://" + host.getHostname() + ":" + quickLinkDTO.getHttpPortDefault();
quickLinkVO.setUrl(url);
return quickLinkVO;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,7 @@ public class ComponentModel {
@XmlElementWrapper(name = "custom-commands")
@XmlElements(@XmlElement(name = "custom-command"))
private List<CustomCommandModel> customCommands;

@XmlElement(name = "quick-link")
private QuickLinkModel quickLink;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,28 @@
*/
package org.apache.bigtop.manager.server.stack.pojo;

public class QuickLinkModel {}
import lombok.Data;

import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElement;

@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class QuickLinkModel {

@XmlElement(name = "display-name")
private String displayName;

@XmlElement(name = "http-port-property")
private String httpPortProperty;

@XmlElement(name = "http-port-default")
private String httpPortDefault;

@XmlElement(name = "https-port-property")
private String httpsPortProperty;

@XmlElement(name = "https-port-default")
private String httpsPortDefault;
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@
</property>
<property>
<name>dfs.namenode.rpc-address</name>
<value>localhost:8020</value>
<value>0.0.0.0:8020</value>
<description>RPC address that handles all clients requests.</description>
</property>
<property>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@
</command-script>
</custom-command>
</custom-commands>
<quick-link>
<display-name>NameNode UI</display-name>
<http-port-property>dfs.namenode.http-address</http-port-property>
<http-port-default>50070</http-port-default>
<https-port-property>dfs.namenode.http-address</https-port-property>
<https-port-default>50470</https-port-default>
</quick-link>
</component>
<component>
<name>datanode</name>
Expand Down
Loading

0 comments on commit a9aa638

Please sign in to comment.