Skip to content

Commit

Permalink
feat(network-api): 자신의 내부 아이피를 주기적으로 main-api에 저장하는 기능
Browse files Browse the repository at this point in the history
  • Loading branch information
inferior3x committed Jan 13, 2025
1 parent 168323f commit cd2e72c
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.whoz_in.network_api.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.whoz_in.network_api.private_ip;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;

//http로 알리도록 구현
@Slf4j
@Component
public final class HttpPrivateIpWriter implements PrivateIpWriter {
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper;
private final String mainApiBaseUrl;
private final String mainApiKey;

public HttpPrivateIpWriter(RestTemplate restTemplate, ObjectMapper objectMapper,
@Value("${main-api.base-url}") String mainApiBaseUrl,
@Value("${main-api.api-key}") String mainApiKey) {
this.restTemplate = restTemplate;
this.objectMapper = objectMapper;
this.mainApiBaseUrl = mainApiBaseUrl;
this.mainApiKey = mainApiKey;
}

//TODO: 다른 요청도 하게 되면 공통 로직 묶기
@Override
public boolean write(String room, Map<String, String> privateIps) {

HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", mainApiKey);
headers.set("Content-Type", "application/json");

HttpEntity<String> requestEntity = new HttpEntity<>(createRequestBody(room, privateIps), headers);

try {
restTemplate.exchange(
mainApiBaseUrl + "/api/v1/private-ip",
HttpMethod.PUT,
requestEntity,
Void.class
);
return true;
} catch (ResourceAccessException e){
log.error("main api에 접근할 수 없음 : {}", e.getMessage()); //서버가 꺼져있는지 확인
} catch (HttpClientErrorException.Forbidden e) {
log.error("Api key 인증 실패 : {}", e.getMessage());
} catch (Exception e) {
log.error("알 수 없는 예외 : {}", e.getMessage());
}
return false;
}

private String createRequestBody(String room, Map<String, String> privateIps) {
try {
return objectMapper.writeValueAsString(Map.of(
"room", room,
"private_ip_list", privateIps
));
} catch (JsonProcessingException e) {
throw new RuntimeException("Failed to serialize request body", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.whoz_in.network_api.private_ip;

import com.whoz_in.network_api.common.NetworkInterface;
import com.whoz_in.network_api.config.NetworkConfig;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

//주기적으로 자신의 내부 아이피를 알아내고 PrivateIpWriter를 이용하여 main-api에 저장
@Slf4j
@Component
@RequiredArgsConstructor
public class PrivateIpUpdater {
private Map<String, String> sent = Map.of();
private final NetworkConfig networkConfig;
private final PrivateIpWriter writer;

@Scheduled(fixedRate = 30000)
private void update() {
Map<String, String> privateIp = getPrivateIpPerSsid();
if (sent.equals(privateIp))
return;
if (writer.write(networkConfig.getRoom(), privateIp)) {
sent = privateIp;
log.info("[private ip] updated");
}
}

private Map<String, String> getPrivateIpPerSsid(){
List<NetworkInterface> networkInterfaces = networkConfig.getManagedNIs();
//아이피를 얻지 못했을 경우 담지 않는다.
Map<String, String> privateIps = new HashMap<>();
for (NetworkInterface ni : networkInterfaces) {
SystemPrivateIpResolver.getIPv4(ni.getInterfaceName())
.ifPresent(ip->privateIps.put(ni.getAltSsid(), ip));
}
return privateIps;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.whoz_in.network_api.private_ip;

import java.util.Map;

//main-api에게 자신(network-api)이 가진 내부 아이피를 알리는 기능
public interface PrivateIpWriter {
//반환 값은 성공 여부를 나타낸다.
boolean write(String room, Map<String, String> privateIps); //Map<방, Optional<아이피>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.whoz_in.network_api.private_ip;

import java.net.InetAddress;
import java.net.SocketException;
import java.util.Collections;
import java.util.Optional;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

//내부 아이피를 알아내는 클래스
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class SystemPrivateIpResolver {
public static Optional<String> getIPv4(String interfaceName) {
try {
return Collections.list(java.net.NetworkInterface.getNetworkInterfaces()).stream()
.filter(networkInterface -> networkInterface.getName().equals(interfaceName))
.flatMap(networkInterface -> Collections.list(networkInterface.getInetAddresses()).stream())
.filter(address -> !address.isLoopbackAddress() && address instanceof java.net.Inet4Address)
.map(InetAddress::getHostAddress)
.findAny();
} catch (SocketException e) {
throw new IllegalStateException("시스템에 네트워크 인터페이스가 아예 존재하지 않음");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@ command:

sudo_password: ${SUDO_PASSWORD}

main-api:
base-url: ${MAIN_API_BASE_URL}
api-key: ${MAIN_API_API_KEY}

logging:
config: "classpath:logback-common.xml"

0 comments on commit cd2e72c

Please sign in to comment.