package cn.seecoder.devmanage.service.impl; import cn.seecoder.api.k8s.model.LimitRange; import cn.seecoder.devmanage.log.LocalLogger; import cn.seecoder.devmanage.model.po.LimitRequest; import cn.seecoder.devmanage.model.vo.LimitRequestVO; import cn.seecoder.devmanage.repository.LimitRequestRepository; import cn.seecoder.devmanage.service.LimitRangeService; import cn.seecoder.devmanage.service.LimitRequestService; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.*; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @Service @RequiredArgsConstructor public class LimitRequestServiceImpl implements LimitRequestService { private final LocalLogger localLogger; private final LimitRangeService limitRangeService; private final LimitRequestRepository limitRequestRepository; private final int[] validPageSizes = new int[]{5, 10, 20}; private final String[] HANDLED_MATCHES = {"已处理", "handled", "handle", "已审阅", "已操作", "true"}; private final String[] UNHANDLED_MATCHES = {"未处理", "unhandled", "unhandle", "未审阅", "未操作", "false"}; private final String[] PERMITTED_MATCHES = {"已允许", "允许", "permitted", "permit", "已获准", "获准", "已准许", "准许", "true"}; private final String[] DENIED_MATCHES = {"未允许", "未获准", "未准许", "deny", "denied", "unpermitted", "unpermit", "false"}; private final int ALL_REQUEST = 0; private final int ONLY_HANDLED = 1; private final int ONLY_UNHANDLED = 2; @Transactional @Override public LimitRequestVO newLimitRequest(String namespace, String name, Integer maxCpu, Integer maxMem, String reason) { String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); LimitRequest limitRequest = new LimitRequest(username, namespace, name, maxMem, maxCpu, false, false, System.currentTimeMillis(), reason); LimitRequest save = limitRequestRepository.save(limitRequest); return new LimitRequestVO(save); } @Transactional(readOnly = true) @Override public List getPagedLimitRequests(Integer pageNo, Integer pageSize, Boolean descByTime, Integer handledSwitch) { if (isInvalidPageSize(pageSize)) { return new ArrayList<>(); } Page results; Sort sort = descByTime ? Sort.by("timestamp").descending() : Sort.by("timestamp").ascending(); if (handledSwitch == ALL_REQUEST) { results = limitRequestRepository.findAll(PageRequest.of(pageNo, pageSize, sort)); } else if (handledSwitch == ONLY_HANDLED || handledSwitch == ONLY_UNHANDLED) { boolean handled = handledSwitch == ONLY_HANDLED; LimitRequest probe = new LimitRequest(); probe.setHandled(handled); ExampleMatcher matcher = ExampleMatcher.matchingAll() .withMatcher("handled", ExampleMatcher.GenericPropertyMatchers.exact()); Example example = Example.of(probe, matcher); results = limitRequestRepository.findAll(example, PageRequest.of(pageNo, pageSize, sort)); } else { return new ArrayList<>(); } List ans = new ArrayList<>(pageSize); for (LimitRequest po: results) { ans.add(new LimitRequestVO(po)); } return ans; } @Transactional(readOnly = true) @Override public List searchPagedLimitRequests(Integer pageNo, Integer pageSize, String keyword, Boolean descByTime) { if (isInvalidPageSize(pageSize) || keyword == null) { return new ArrayList<>(); } Sort sort = descByTime ? Sort.by("timestamp").descending() : Sort.by("timestamp").ascending(); LimitRequest probe = new LimitRequest(); probe.setRequester(keyword); probe.setNamespace(keyword); probe.setName(keyword); // String keywords ExampleMatcher matcher = ExampleMatcher.matchingAny() .withIgnoreCase() .withMatcher("requester", ExampleMatcher.GenericPropertyMatchers.contains()) .withMatcher("namespace", ExampleMatcher.GenericPropertyMatchers.contains()) .withMatcher("name", ExampleMatcher.GenericPropertyMatchers.contains()); // Long keyword if (isParsableLong(keyword)) { probe.setId(Long.parseLong(keyword)); matcher = matcher.withMatcher("id", ExampleMatcher.GenericPropertyMatchers.exact()); } // Integer keywords if (isParsableInteger(keyword)) { int intKey = Integer.parseInt(keyword); probe.setMaxMem(intKey); probe.setMaxCpu(intKey); matcher = matcher .withMatcher("maxMem", ExampleMatcher.GenericPropertyMatchers.exact()) .withMatcher("maxCpu", ExampleMatcher.GenericPropertyMatchers.exact()); } // Handled if (Arrays.stream(HANDLED_MATCHES).anyMatch(keyword::equalsIgnoreCase)) { probe.setHandled(true); matcher = matcher.withMatcher("handled", ExampleMatcher.GenericPropertyMatchers.exact()); } else if (Arrays.stream(UNHANDLED_MATCHES).anyMatch(keyword::equalsIgnoreCase)) { probe.setHandled(false); matcher = matcher.withMatcher("handled", ExampleMatcher.GenericPropertyMatchers.exact()); } // Permitted if (Arrays.stream(PERMITTED_MATCHES).anyMatch(keyword::equalsIgnoreCase)) { probe.setPermitted(true); matcher = matcher.withMatcher("permitted", ExampleMatcher.GenericPropertyMatchers.exact()); } else if (Arrays.stream(DENIED_MATCHES).anyMatch(keyword::equalsIgnoreCase)) { probe.setPermitted(false); matcher = matcher.withMatcher("permitted", ExampleMatcher.GenericPropertyMatchers.exact()); } Example example = Example.of(probe, matcher); Page results = limitRequestRepository.findAll(example, PageRequest.of(pageNo, pageSize, sort)); List ans = new ArrayList<>(); for (LimitRequest po: results) { ans.add(new LimitRequestVO(po)); } return ans; } @Transactional @Override public boolean permitRequest(Long limitRequestId) { LimitRequest limitRequest = limitRequestRepository.getById(limitRequestId); if (limitRequest.getHandled()) { // You can not handle an already handled request localLogger.recordFailure( String.format("Tried to illegally permit an already handled LimitRequest, which id is %s.", limitRequestId)); return false; } else { limitRequest.setHandled(true); limitRequest.setPermitted(true); String namespace = limitRequest.getNamespace(); String name = limitRequest.getName(); List limitRanges = limitRangeService.getLimitRanges(namespace, name); if (limitRanges == null || limitRanges.isEmpty()) { localLogger.recordFailure(String.format("Targeted LimitRange of id %s doest not exist, thus" + " did nothing.", limitRequestId)); return false; } else { LimitRange limitRange = limitRanges.get(0); Integer maxCpu = limitRequest.getMaxCpu(); Integer maxMem = limitRequest.getMaxMem(); limitRange.setMaxCpu(maxCpu + "m"); limitRange.setMaxMemory(maxMem + "Mi"); limitRangeService.updateLimitRange(limitRange); localLogger.recordSuccess(String.format("Permitted a LimitRequest, which id is %s", limitRequestId)); return true; } } } @Transactional @Override public boolean denyRequest(Long limitRequestId) { LimitRequest limitRequest = limitRequestRepository.getById(limitRequestId); if (limitRequest.getHandled()) { // You can not handle an already handled request localLogger.recordFailure( String.format("Tried to illegally deny an already handled LimitRequest, which id is %s.", limitRequestId)); return false; } else { limitRequest.setHandled(true); limitRequest.setPermitted(false); localLogger.recordSuccess(String.format("Denied a LimitRequest, which id is %s", limitRequestId)); return true; } } @Override public Integer getTotalPageCount(Integer pageSize) { if (isInvalidPageSize(pageSize)) { return 0; } else { long count = limitRequestRepository.count(); if (count % pageSize == 0) { return Math.toIntExact(count / pageSize); } else { return Math.toIntExact(count / pageSize + 1); } } } private boolean isParsableLong(String keyword) { try { Long.parseLong(keyword); return true; } catch (NumberFormatException e) { return false; } } private boolean isParsableInteger(String keyword) { try { Integer.parseInt(keyword); return true; } catch (NumberFormatException e) { return false; } } private boolean isInvalidPageSize(Integer pageSize) { for (int validPageSize: validPageSizes) { if (validPageSize == pageSize) { return false; } } return true; } }