Skip to content

Commit

Permalink
BIGTOP-4163: Add quick links for service
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinw66 committed Jul 16, 2024
1 parent ae8e43d commit b0af891
Show file tree
Hide file tree
Showing 20 changed files with 240 additions and 21 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,27 @@
*/
package org.apache.bigtop.manager.server.stack.pojo;

public class QuickLinkModel {}
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElement;
import lombok.Data;

@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 @@ -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
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>ResourceManager UI</display-name>
<http-port-property>yarn.resourcemanager.webapp.address</http-port-property>
<http-port-default>8088</http-port-default>
<https-port-property>yarn.resourcemanager.webapp.https.address</https-port-property>
<https-port-default>8090</https-port-default>
</quick-link>
</component>
<component>
<name>nodemanager</name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@
<script-type>java</script-type>
<timeout>1200</timeout>
</command-script>
<quick-link>
<display-name>ZooKeeper UI(Test)</display-name>
<http-port-property>admin.serverPort</http-port-property>
<http-port-default>9393</http-port-default>
<https-port-property>admin.serverPort</https-port-property>
<https-port-default>9393</https-port-default>
</quick-link>
</component>

<component>
Expand Down
6 changes: 6 additions & 0 deletions bigtop-manager-ui/src/api/service/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,10 @@ export interface ServiceVO {
serviceGroup?: string
isClient?: boolean
isHealthy?: boolean
quickLinks?: QuickLinkVO[]
}

export interface QuickLinkVO {
displayName: string
url: string
}
3 changes: 2 additions & 1 deletion bigtop-manager-ui/src/locales/en_US/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ export default {
summary: 'Summary',
config: 'Config',
components: 'Components',
quicklinks: 'Quick Links'
quick_links: 'Quick Links',
no_link: 'No Link'
}
Loading

0 comments on commit b0af891

Please sign in to comment.