mirror of
https://github.com/LamGC/Oracle-Sentry.git
synced 2025-04-29 14:17:34 +00:00
feat: 重做 Oracle Identity 相关组件, 为脚本提供访问 Oracle Account 的组件.
重做 OracleIdentityManager, 增加 OracleAccount 与 OracleClients 对象, 使脚本可以访问 SDK, 执行更多操作. 调整 ComputeInstance 与 InstanceNetwork, SDK Client 不再直接创建, 而是使用 OracleClients 中的客户端单例.
This commit is contained in:
parent
6b2bd0a59d
commit
bec7010d43
@ -1,7 +1,8 @@
|
||||
package net.lamgc.oracle.sentry;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.oracle.bmc.auth.AuthenticationDetailsProvider;
|
||||
import net.lamgc.oracle.sentry.oci.account.OracleAccount;
|
||||
import net.lamgc.oracle.sentry.oci.account.OracleAccountManager;
|
||||
import net.lamgc.oracle.sentry.script.ScriptComponents;
|
||||
import net.lamgc.oracle.sentry.script.ScriptLoggerFactory;
|
||||
import net.lamgc.oracle.sentry.script.ScriptManager;
|
||||
@ -48,8 +49,8 @@ class ApplicationInitiation {
|
||||
private String sshIdentityPath;
|
||||
|
||||
@Bean("oracle.identity.manager")
|
||||
public OracleIdentityManager initialOracleIdentityManager() throws IOException {
|
||||
OracleIdentityManager oracleUserManager = new OracleIdentityManager();
|
||||
public OracleAccountManager initialOracleAccountManager() throws IOException {
|
||||
OracleAccountManager oracleUserManager = new OracleAccountManager();
|
||||
log.info("正在加载 Oracle API 身份配置...");
|
||||
log.debug("Oracle API 身份配置查找路径: \"{}\", 匹配表达式: {}", identityDirectory, identityFilePattern);
|
||||
File identityDir = new File(identityDirectory);
|
||||
@ -68,15 +69,15 @@ class ApplicationInitiation {
|
||||
|
||||
@Bean("oracle.compute.instance.manager")
|
||||
@Autowired
|
||||
public ComputeInstanceManager initialComputeInstanceManager(OracleIdentityManager identityManager) throws IOException {
|
||||
public ComputeInstanceManager initialComputeInstanceManager(OracleAccountManager accountManager) throws IOException {
|
||||
ComputeInstanceManager instanceManager = new ComputeInstanceManager();
|
||||
int addTotal = 0;
|
||||
for (AuthenticationDetailsProvider provider : identityManager.getProviders()) {
|
||||
String identityName = identityManager.getIdentityName(provider.getUserId());
|
||||
for (OracleAccount account : accountManager.getAccounts()) {
|
||||
String identityName = account.name();
|
||||
log.info("正在加载用户 {} 所拥有的所有实例...", identityName);
|
||||
int addCount;
|
||||
try {
|
||||
addCount = instanceManager.addComputeInstanceFromUser(provider);
|
||||
addCount = instanceManager.addComputeInstanceFromUser(account);
|
||||
} catch (Exception e) {
|
||||
log.error("加载实例时发生异常.", e);
|
||||
continue;
|
||||
@ -93,11 +94,12 @@ class ApplicationInitiation {
|
||||
|
||||
@Bean("sentry.script.manager")
|
||||
@Autowired
|
||||
public ScriptManager initialScriptManager(ComputeInstanceManager instanceManager) {
|
||||
public ScriptManager initialScriptManager(ComputeInstanceManager instanceManager, OracleAccountManager accountManager) {
|
||||
ScriptComponents context = new ScriptComponents(new ScriptHttpClient(HttpClientBuilder.create()
|
||||
.build()),
|
||||
instanceManager,
|
||||
new ScriptLoggerFactory()
|
||||
new ScriptLoggerFactory(),
|
||||
accountManager
|
||||
);
|
||||
|
||||
ScriptManager manager = new ScriptManager(new File(scriptsLocation), context);
|
||||
|
@ -1,20 +1,21 @@
|
||||
package net.lamgc.oracle.sentry;
|
||||
|
||||
import com.oracle.bmc.auth.AuthenticationDetailsProvider;
|
||||
import com.oracle.bmc.core.ComputeClient;
|
||||
import com.oracle.bmc.core.model.Instance;
|
||||
import com.oracle.bmc.core.requests.ListInstancesRequest;
|
||||
import com.oracle.bmc.core.responses.ListInstancesResponse;
|
||||
import com.oracle.bmc.identity.IdentityClient;
|
||||
import com.oracle.bmc.identity.model.Compartment;
|
||||
import com.oracle.bmc.identity.requests.ListCompartmentsRequest;
|
||||
import com.oracle.bmc.identity.responses.ListCompartmentsResponse;
|
||||
import net.lamgc.oracle.sentry.oci.account.OracleAccount;
|
||||
import net.lamgc.oracle.sentry.oci.compute.ComputeInstance;
|
||||
import net.lamgc.oracle.sentry.oci.compute.ssh.SshAuthIdentityProvider;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -64,37 +65,37 @@ public final class ComputeInstanceManager {
|
||||
public Set<ComputeInstance> getInstancesByUserId(String userId) {
|
||||
Objects.requireNonNull(userId);
|
||||
return instanceMap.values().stream()
|
||||
.filter(computeInstance -> computeInstance.getUserId().equals(userId))
|
||||
.filter(computeInstance -> computeInstance.getFromAccount().id().equals(userId))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加某一用户的所有计算实例.
|
||||
* @param provider 用户身份提供器.
|
||||
* @param account Oracle 云账号对象.
|
||||
* @return 返回已成功添加的实例数量.
|
||||
* @throws NullPointerException 如果 provider 为 {@code null} 则抛出异常.
|
||||
*/
|
||||
public int addComputeInstanceFromUser(AuthenticationDetailsProvider provider) {
|
||||
Objects.requireNonNull(provider);
|
||||
IdentityClient identityClient = new IdentityClient(provider);
|
||||
ComputeClient computeClient = new ComputeClient(provider);
|
||||
ListCompartmentsResponse listCompartments = identityClient.listCompartments(ListCompartmentsRequest.builder()
|
||||
.compartmentId(provider.getTenantId())
|
||||
.build());
|
||||
public int addComputeInstanceFromUser(OracleAccount account) {
|
||||
Objects.requireNonNull(account);
|
||||
ListCompartmentsResponse listCompartments = account.clients().identity()
|
||||
.listCompartments(ListCompartmentsRequest.builder()
|
||||
.compartmentId(account.tenantId())
|
||||
.build());
|
||||
int addCount = 0;
|
||||
Set<String> compartmentIds = listCompartments.getItems().stream()
|
||||
.map(Compartment::getId).collect(Collectors.toSet());
|
||||
compartmentIds.add(provider.getTenantId());
|
||||
compartmentIds.add(account.tenantId());
|
||||
for (String compartmentId : compartmentIds) {
|
||||
ListInstancesResponse listInstances = computeClient.listInstances(ListInstancesRequest.builder()
|
||||
.compartmentId(compartmentId)
|
||||
.build());
|
||||
ListInstancesResponse listInstances = account.clients().compute()
|
||||
.listInstances(ListInstancesRequest.builder()
|
||||
.compartmentId(compartmentId)
|
||||
.build());
|
||||
for (Instance instance : listInstances.getItems()) {
|
||||
if (instance.getLifecycleState() == Instance.LifecycleState.Terminated) {
|
||||
continue;
|
||||
}
|
||||
ComputeInstance computeInstance = new ComputeInstance(this, instance.getId(),
|
||||
provider.getUserId(), compartmentId, instance.getImageId(), provider);
|
||||
compartmentId, instance.getImageId(), account);
|
||||
|
||||
addComputeInstance(computeInstance);
|
||||
addCount ++;
|
||||
|
48
src/main/java/net/lamgc/oracle/sentry/common/LazyLoader.java
Normal file
48
src/main/java/net/lamgc/oracle/sentry/common/LazyLoader.java
Normal file
@ -0,0 +1,48 @@
|
||||
package net.lamgc.oracle.sentry.common;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 惰性加载器.
|
||||
* <p> 该加载器只会在第一次获取对象时初始化.
|
||||
* <p> 如果不用, 可能会导致内存消耗增加, 尤其是在管理大量帐号的情况下.
|
||||
* <p> 对象在本加载器中为单例, 任何通过同一个加载器获取的对象都是同一个对象.
|
||||
* @author LamGC
|
||||
* @param <T> 对象类型.
|
||||
*/
|
||||
public final class LazyLoader<T> {
|
||||
|
||||
private final Supplier<T> supplier;
|
||||
private final AtomicReference<T> object = new AtomicReference<>(null);
|
||||
|
||||
/**
|
||||
* 构建惰性加载器.
|
||||
* @param supplier 对象提供器.
|
||||
*/
|
||||
public LazyLoader(Supplier<T> supplier) {
|
||||
this.supplier = Objects.requireNonNull(supplier);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象.
|
||||
* <p> 如果是首次调用本方法, 本方法将通过 Supplier 获取一个对象, 缓存对象后返回.
|
||||
* @return 返回惰性加载的对象.
|
||||
*/
|
||||
public T getInstance() {
|
||||
if (object.get() == null) {
|
||||
synchronized (this) {
|
||||
if (object.get() == null) {
|
||||
T newInstance = supplier.get();
|
||||
if (newInstance == null) {
|
||||
throw new NullPointerException("Supplier is not allowed to return null.");
|
||||
}
|
||||
return object.compareAndSet(null, newInstance) ? newInstance : object.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
return object.get();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package net.lamgc.oracle.sentry.oci.account;
|
||||
|
||||
import com.oracle.bmc.auth.AuthenticationDetailsProvider;
|
||||
import com.oracle.bmc.identity.model.User;
|
||||
import com.oracle.bmc.identity.requests.GetUserRequest;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Oracle 云账户.
|
||||
* @author LamGC
|
||||
*/
|
||||
public final class OracleAccount {
|
||||
|
||||
private final AuthenticationDetailsProvider provider;
|
||||
private final OracleClients clients;
|
||||
private final User user;
|
||||
|
||||
OracleAccount(AuthenticationDetailsProvider provider) {
|
||||
this.provider = Objects.requireNonNull(provider);
|
||||
this.clients = new OracleClients(provider);
|
||||
this.user = clients.identity().getUser(GetUserRequest.builder()
|
||||
.userId(provider.getUserId())
|
||||
.build()).getUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取帐号 Id.
|
||||
* @return 返回帐号 OCID.
|
||||
*/
|
||||
public String id() {
|
||||
return provider.getUserId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取租户 Id.
|
||||
* <p> 该 Id 同时也是根区间 Id.
|
||||
* @return 返回租户 Id.
|
||||
*/
|
||||
public String tenantId() {
|
||||
return provider.getTenantId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户名.
|
||||
* @return 返回用户名称.
|
||||
*/
|
||||
public String name() {
|
||||
return this.user.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户说明信息.
|
||||
* @return 返回设定的用户说明信息.
|
||||
*/
|
||||
public String description() {
|
||||
return this.user.getDescription();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取该账户所属的 API 客户端集合.
|
||||
* @return 返回该账户所属的甲骨文 API 客户端集.
|
||||
*/
|
||||
public OracleClients clients() {
|
||||
return clients;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
AuthenticationDetailsProvider thatProvider = ((OracleAccount) o).provider;
|
||||
return provider.getUserId().equals(thatProvider.getUserId()) &&
|
||||
provider.getTenantId().equals(thatProvider.getTenantId()) &&
|
||||
provider.getFingerprint().equals(thatProvider.getFingerprint()) &&
|
||||
provider.getKeyId().equals(thatProvider.getKeyId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(provider.getUserId(), provider.getTenantId(), provider.getFingerprint(), provider.getKeyId());
|
||||
}
|
||||
|
||||
}
|
@ -1,17 +1,12 @@
|
||||
package net.lamgc.oracle.sentry;
|
||||
package net.lamgc.oracle.sentry.oci.account;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.oracle.bmc.ConfigFileReader;
|
||||
import com.oracle.bmc.Region;
|
||||
import com.oracle.bmc.auth.AuthenticationDetailsProvider;
|
||||
import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider;
|
||||
import com.oracle.bmc.auth.SimplePrivateKeySupplier;
|
||||
import com.oracle.bmc.identity.IdentityClient;
|
||||
import com.oracle.bmc.identity.requests.GetUserRequest;
|
||||
import com.oracle.bmc.identity.responses.GetUserResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -28,25 +23,19 @@ import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Oracle 身份管理器.
|
||||
* Oracle 云账号管理器.
|
||||
* @author LamGC
|
||||
*/
|
||||
public final class OracleIdentityManager {
|
||||
public final class OracleAccountManager {
|
||||
|
||||
private final static Logger log = LoggerFactory.getLogger(OracleIdentityManager.class);
|
||||
private final static Logger log = LoggerFactory.getLogger(OracleAccountManager.class);
|
||||
|
||||
/**
|
||||
* 认证身份 Map.
|
||||
* Key: Identity Id
|
||||
* Value {@link AuthenticationDetailsProvider}
|
||||
*/
|
||||
private final Map<String, AuthenticationDetailsProvider> identityMap = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* 用户名 Map.
|
||||
* key Identity Id
|
||||
* Value: Username
|
||||
*/
|
||||
private final Map<String, String> identityNameMap = new ConcurrentHashMap<>();
|
||||
private final Map<String, OracleAccount> accountMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 从目录扫描匹配的配置文件并加载.
|
||||
@ -69,14 +58,14 @@ public final class OracleIdentityManager {
|
||||
int loadedCount = 0;
|
||||
for (File configFile : configFiles) {
|
||||
try {
|
||||
AuthenticationDetailsProvider provider = loadFromConfigFile(configFile);
|
||||
if (provider == null) {
|
||||
OracleAccount account = loadFromConfigFile(configFile);
|
||||
if (account == null) {
|
||||
continue;
|
||||
}
|
||||
loadedCount ++;
|
||||
log.info("已成功加载身份配置文件.\n\tUserId: {}\n\tUsername: {}\n\tPath: {}",
|
||||
provider.getUserId(),
|
||||
getIdentityName(provider.getUserId()),
|
||||
account.id(),
|
||||
account.name(),
|
||||
configFile.getCanonicalPath());
|
||||
} catch (Exception e) {
|
||||
log.error("加载身份配置文件时发生异常.(Path: {})\n{}", configFile.getCanonicalPath(), Throwables.getStackTraceAsString(e));
|
||||
@ -92,7 +81,7 @@ public final class OracleIdentityManager {
|
||||
* @return 返回已成功加载后, 配置文件对应的身份配置提供器.
|
||||
* @throws IOException 如果读取文件发生问题时将抛出该异常.
|
||||
*/
|
||||
public AuthenticationDetailsProvider loadFromConfigFile(File identityConfig) throws IOException {
|
||||
public OracleAccount loadFromConfigFile(File identityConfig) throws IOException {
|
||||
if (!identityConfig.exists()) {
|
||||
throw new FileNotFoundException(identityConfig.getAbsolutePath());
|
||||
}
|
||||
@ -122,10 +111,14 @@ public final class OracleIdentityManager {
|
||||
.build();
|
||||
|
||||
// 尝试获取身份所属用户名, 以此检查该身份配置是否正确.
|
||||
String identityName = getIdentityName0(provider);
|
||||
identityNameMap.put(provider.getUserId(), identityName);
|
||||
identityMap.put(provider.getUserId(), provider);
|
||||
return provider;
|
||||
OracleAccount oracleAccount = new OracleAccount(provider);
|
||||
String accountName = oracleAccount.name();
|
||||
if (accountName == null) {
|
||||
throw new NullPointerException("Failed to obtain the account name. The identity configuration may be incorrect.");
|
||||
}
|
||||
log.debug("已成功通过身份配置获取用户名称: {}", accountName);
|
||||
accountMap.put(oracleAccount.id(), oracleAccount);
|
||||
return oracleAccount;
|
||||
}
|
||||
|
||||
private boolean checkIdentityProfileConfig(ConfigFileReader.ConfigFile config) {
|
||||
@ -144,35 +137,6 @@ public final class OracleIdentityManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取身份所属用户的名称.
|
||||
* @param provider 身份提供器.
|
||||
* @return 返回用户名.
|
||||
*/
|
||||
private String getIdentityName0(AuthenticationDetailsProvider provider) {
|
||||
IdentityClient identityClient = new IdentityClient(provider);
|
||||
GetUserResponse user = identityClient.getUser(GetUserRequest.builder()
|
||||
.userId(provider.getUserId())
|
||||
.build());
|
||||
return user.getUser().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取身份信息所属的用户名.
|
||||
* @param userId 身份信息所属的用户 Id.
|
||||
* @return 返回用户名.
|
||||
* @throws NullPointerException 当 userId 为 {@code null} 时抛出该异常.
|
||||
* @throws NoSuchElementException 指定的 UserId 未找到对应用户名时抛出该异常.
|
||||
*/
|
||||
public String getIdentityName(String userId) {
|
||||
Objects.requireNonNull(userId);
|
||||
if (!identityMap.containsKey(userId)) {
|
||||
throw new NoSuchElementException(userId);
|
||||
}
|
||||
return identityNameMap.get(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 UserId 获取指定身份提供器.
|
||||
* @param userId 用户 Id.
|
||||
@ -180,37 +144,20 @@ public final class OracleIdentityManager {
|
||||
* @throws NullPointerException 当 userId 为 {@code null} 时抛出该异常.
|
||||
* @throws NoSuchElementException 指定的 UserId 未找到对应 Provider 时抛出该异常.
|
||||
*/
|
||||
public AuthenticationDetailsProvider getProviderByUserId(String userId) {
|
||||
public OracleAccount getAccountByUserId(String userId) {
|
||||
Objects.requireNonNull(userId);
|
||||
if (!identityMap.containsKey(userId)) {
|
||||
if (!accountMap.containsKey(userId)) {
|
||||
throw new NoSuchElementException(userId);
|
||||
}
|
||||
return identityMap.get(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出身份信息.
|
||||
* <p> 不包含私钥.
|
||||
* @return 返回 Json 形式的身份信息数组.
|
||||
*/
|
||||
public JsonArray exportIdentityInfo() {
|
||||
JsonArray identityInfoArray = new JsonArray(identityMap.size());
|
||||
for (AuthenticationDetailsProvider provider : identityMap.values()) {
|
||||
JsonObject identity = new JsonObject();
|
||||
identity.addProperty("UserId", provider.getUserId());
|
||||
identity.addProperty("TenantId", provider.getTenantId());
|
||||
identity.addProperty("Fingerprint", provider.getFingerprint());
|
||||
identityInfoArray.add(identity);
|
||||
}
|
||||
return identityInfoArray;
|
||||
return accountMap.get(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有身份提供器.
|
||||
* @return 返回包含所有身份提供器的集合对象.
|
||||
*/
|
||||
public Set<AuthenticationDetailsProvider> getProviders() {
|
||||
return identityMap.values().stream().collect(Collectors.toUnmodifiableSet());
|
||||
public Set<OracleAccount> getAccounts() {
|
||||
return accountMap.values().stream().collect(Collectors.toUnmodifiableSet());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
package net.lamgc.oracle.sentry.oci.account;
|
||||
|
||||
import com.oracle.bmc.auth.AuthenticationDetailsProvider;
|
||||
import com.oracle.bmc.core.BlockstorageClient;
|
||||
import com.oracle.bmc.core.ComputeClient;
|
||||
import com.oracle.bmc.core.VirtualNetworkClient;
|
||||
import com.oracle.bmc.identity.IdentityClient;
|
||||
import com.oracle.bmc.objectstorage.ObjectStorageClient;
|
||||
import net.lamgc.oracle.sentry.common.LazyLoader;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 甲骨文 SDK 客户端.
|
||||
* @author LamGC
|
||||
*/
|
||||
public class OracleClients {
|
||||
|
||||
private final Map<Class<?>, LazyLoader<?>> LAZY_LOADER_MAP = new ConcurrentHashMap<>();
|
||||
private final AuthenticationDetailsProvider provider;
|
||||
|
||||
OracleClients(AuthenticationDetailsProvider provider) {
|
||||
this.provider = Objects.requireNonNull(provider);
|
||||
initialLazyLoad();
|
||||
}
|
||||
|
||||
private void initialLazyLoad() {
|
||||
registryLazyLoader(ComputeClient.class, () -> new ComputeClient(provider));
|
||||
registryLazyLoader(VirtualNetworkClient.class, () -> new VirtualNetworkClient(provider));
|
||||
registryLazyLoader(BlockstorageClient.class, () -> new BlockstorageClient(provider));
|
||||
registryLazyLoader(IdentityClient.class, () -> new IdentityClient(provider));
|
||||
registryLazyLoader(ObjectStorageClient.class, () -> new ObjectStorageClient(provider));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取计算类客户端.
|
||||
* @return 获取计算类客户端对象.
|
||||
*/
|
||||
public ComputeClient compute() {
|
||||
return getInstance(ComputeClient.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取网络客户端.
|
||||
* @return 返回 VCN 操作客户端.
|
||||
*/
|
||||
public VirtualNetworkClient network() {
|
||||
return getInstance(VirtualNetworkClient.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取块存储客户端.
|
||||
* <p> 仅限计算实例的存储.
|
||||
* @return 返回块存储客户端.
|
||||
*/
|
||||
public BlockstorageClient blockStorage() {
|
||||
return getInstance(BlockstorageClient.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取身份客户端.
|
||||
* <p> 用于访问身份相关 API.
|
||||
* @return 返回身份客户端.
|
||||
*/
|
||||
public IdentityClient identity() {
|
||||
return getInstance(IdentityClient.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象存储客户端.
|
||||
* <p> 不包括计算实例的存储.
|
||||
* @return 获取对象存储客户端.
|
||||
*/
|
||||
public ObjectStorageClient objectStorage() {
|
||||
return getInstance(ObjectStorageClient.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实例.
|
||||
* @param type 实例类.
|
||||
* @param <T> 实例类型.
|
||||
* @return 返回对象.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T getInstance(Class<?> type) {
|
||||
Objects.requireNonNull(type);
|
||||
if (!LAZY_LOADER_MAP.containsKey(type)) {
|
||||
throw new NoSuchElementException("No lazy loader of this type was found: " + type);
|
||||
}
|
||||
|
||||
return (T) LAZY_LOADER_MAP.get(type).getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册惰性加载器.
|
||||
* @param type 对象类.
|
||||
* @param supplier 对象提供器.
|
||||
* @param <T> 对象类型.
|
||||
*/
|
||||
private <T> void registryLazyLoader(Class<? extends T> type, Supplier<T> supplier) {
|
||||
Objects.requireNonNull(type);
|
||||
Objects.requireNonNull(supplier);
|
||||
LAZY_LOADER_MAP.put(type, new LazyLoader<>(supplier));
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package net.lamgc.oracle.sentry.oci.compute;
|
||||
|
||||
import com.oracle.bmc.auth.AuthenticationDetailsProvider;
|
||||
import com.oracle.bmc.core.ComputeClient;
|
||||
import com.oracle.bmc.core.model.Instance;
|
||||
import com.oracle.bmc.core.requests.GetImageRequest;
|
||||
@ -10,6 +9,7 @@ import com.oracle.bmc.core.responses.GetImageResponse;
|
||||
import com.oracle.bmc.core.responses.GetInstanceResponse;
|
||||
import com.oracle.bmc.core.responses.InstanceActionResponse;
|
||||
import net.lamgc.oracle.sentry.ComputeInstanceManager;
|
||||
import net.lamgc.oracle.sentry.oci.account.OracleAccount;
|
||||
import net.lamgc.oracle.sentry.oci.compute.ssh.InstanceSsh;
|
||||
import net.lamgc.oracle.sentry.oci.compute.ssh.SshAuthInfo;
|
||||
|
||||
@ -24,11 +24,10 @@ public final class ComputeInstance {
|
||||
private final ComputeInstanceManager instanceManager;
|
||||
|
||||
private final String instanceId;
|
||||
private final String userId;
|
||||
private final String compartmentId;
|
||||
private final String imageId;
|
||||
private final AuthenticationDetailsProvider authProvider;
|
||||
private final InstanceNetwork network;
|
||||
private final OracleAccount fromAccount;
|
||||
|
||||
private final ComputeClient computeClient;
|
||||
|
||||
@ -36,22 +35,20 @@ public final class ComputeInstance {
|
||||
* 构造一个计算实例对象.
|
||||
* @param instanceManager 实例所属的管理器.
|
||||
* @param instanceId 实例 Id.
|
||||
* @param userId 所属用户 Id.
|
||||
* @param compartmentId 实例所在区域的 Id.
|
||||
* @param imageId 镜像 Id.
|
||||
* @param provider 所属用户的身份配置提供器.
|
||||
* @param fromAccount 所属用户的身份配置提供器.
|
||||
*/
|
||||
public ComputeInstance(ComputeInstanceManager instanceManager, String instanceId, String userId,
|
||||
String compartmentId, String imageId, AuthenticationDetailsProvider provider) {
|
||||
public ComputeInstance(ComputeInstanceManager instanceManager, String instanceId,
|
||||
String compartmentId, String imageId, OracleAccount fromAccount) {
|
||||
this.instanceManager = instanceManager;
|
||||
this.instanceId = instanceId;
|
||||
this.userId = userId;
|
||||
this.compartmentId = compartmentId;
|
||||
this.imageId = imageId;
|
||||
this.authProvider = provider;
|
||||
this.fromAccount = fromAccount;
|
||||
|
||||
computeClient = new ComputeClient(provider);
|
||||
this.network = new InstanceNetwork(this);
|
||||
this.computeClient = fromAccount.clients().compute();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -63,14 +60,6 @@ public final class ComputeInstance {
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所属用户的 Id.
|
||||
* @return 返回用户 Id.
|
||||
*/
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务器所属区域的 Id.
|
||||
* <p> 使用的资源必须要处于同一区域, 例如 IP 资源, 磁盘.
|
||||
@ -88,8 +77,8 @@ public final class ComputeInstance {
|
||||
*/
|
||||
public BootImage getImage() {
|
||||
GetImageResponse image = computeClient.getImage(GetImageRequest.builder()
|
||||
.imageId(imageId)
|
||||
.build());
|
||||
.imageId(imageId)
|
||||
.build());
|
||||
return new BootImage(image.getImage());
|
||||
}
|
||||
|
||||
@ -170,10 +159,6 @@ public final class ComputeInstance {
|
||||
return computeClient;
|
||||
}
|
||||
|
||||
AuthenticationDetailsProvider getAuthProvider() {
|
||||
return authProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
@ -183,12 +168,12 @@ public final class ComputeInstance {
|
||||
return false;
|
||||
}
|
||||
ComputeInstance that = (ComputeInstance) o;
|
||||
return instanceId.equals(that.instanceId) && userId.equals(that.userId) && compartmentId.equals(that.compartmentId);
|
||||
return instanceId.equals(that.instanceId) && fromAccount.equals(that.fromAccount) && compartmentId.equals(that.compartmentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(instanceId, userId, compartmentId);
|
||||
return Objects.hash(instanceId, fromAccount, compartmentId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -201,4 +186,11 @@ public final class ComputeInstance {
|
||||
.getAuthInfoByInstanceId(instanceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实例所属的 Oracle 云帐号对象.
|
||||
* @return 返回实例所属帐号对象.
|
||||
*/
|
||||
public OracleAccount getFromAccount() {
|
||||
return fromAccount;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ public class InstanceNetwork {
|
||||
|
||||
InstanceNetwork(ComputeInstance instance) {
|
||||
this.instance = instance;
|
||||
this.vcnClient = new VirtualNetworkClient(this.instance.getAuthProvider());
|
||||
this.vcnClient = instance.getFromAccount().clients().network();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.lamgc.oracle.sentry.script;
|
||||
|
||||
import net.lamgc.oracle.sentry.ComputeInstanceManager;
|
||||
import net.lamgc.oracle.sentry.oci.account.OracleAccountManager;
|
||||
import net.lamgc.oracle.sentry.script.tools.http.ScriptHttpClient;
|
||||
|
||||
/**
|
||||
@ -12,7 +13,8 @@ import net.lamgc.oracle.sentry.script.tools.http.ScriptHttpClient;
|
||||
public final record ScriptComponents(
|
||||
ScriptHttpClient HTTP,
|
||||
ComputeInstanceManager InstanceManager,
|
||||
ScriptLoggerFactory loggerFactory
|
||||
ScriptLoggerFactory loggerFactory,
|
||||
OracleAccountManager AccountManager
|
||||
) {
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,63 @@
|
||||
package net.lamgc.oracle.sentry.common;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class LazyLoaderTest {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void lazyLoadTest() throws NoSuchFieldException, IllegalAccessException {
|
||||
LazyLoader<Object> loader = new LazyLoader<>(Object::new);
|
||||
|
||||
Field field = LazyLoader.class.getDeclaredField("object");
|
||||
field.setAccessible(true);
|
||||
AtomicReference reference = (AtomicReference) field.get(loader);
|
||||
assertNotNull(reference);
|
||||
assertNull(reference.get());
|
||||
Object instance = loader.getInstance();
|
||||
assertEquals(reference.get(), instance);
|
||||
assertEquals(reference.get(), loader.getInstance());
|
||||
assertEquals(instance, loader.getInstance());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("StatementWithEmptyBody")
|
||||
public void multiThreadAccessTest() {
|
||||
class Singleton {
|
||||
private final static AtomicInteger constructNum = new AtomicInteger(0);
|
||||
public Singleton() {
|
||||
if (constructNum.incrementAndGet() > 1) {
|
||||
fail("Multiple instances were generated.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final LazyLoader<Singleton> loader = new LazyLoader<>(Singleton::new);
|
||||
AtomicBoolean start = new AtomicBoolean(false);
|
||||
int threadNum = Runtime.getRuntime().availableProcessors();
|
||||
List<Thread> threads = new ArrayList<>(threadNum);
|
||||
for (int i = 0; i < threadNum; i++) {
|
||||
Thread thread = new Thread(() -> {
|
||||
while (!start.get()) {
|
||||
}
|
||||
assertNotNull(loader.getInstance());
|
||||
});
|
||||
threads.add(thread);
|
||||
}
|
||||
for (Thread thread : threads) {
|
||||
thread.start();
|
||||
}
|
||||
start.set(true);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package net.lamgc.oracle.sentry.script;
|
||||
|
||||
import net.lamgc.oracle.sentry.ComputeInstanceManager;
|
||||
import net.lamgc.oracle.sentry.oci.account.OracleAccountManager;
|
||||
import net.lamgc.oracle.sentry.script.tools.http.ScriptHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -13,7 +14,7 @@ class ScriptManagerTest {
|
||||
public void loadScriptTest() {
|
||||
ScriptManager manager = new ScriptManager(new File("./run/scripts"),
|
||||
new ScriptComponents(new ScriptHttpClient(HttpClientBuilder.create().build()),
|
||||
new ComputeInstanceManager(), new ScriptLoggerFactory()));
|
||||
new ComputeInstanceManager(), new ScriptLoggerFactory(), new OracleAccountManager()));
|
||||
|
||||
manager.loadScripts();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user