| /* |
| * 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 |
| * |
| * http://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.netbeans.modules.cloud.oracle; |
| |
| import com.oracle.bmc.ConfigFileReader; |
| import com.oracle.bmc.Region; |
| import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider; |
| import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider; |
| import com.oracle.bmc.database.DatabaseClient; |
| import com.oracle.bmc.database.model.CreateAutonomousDatabaseBase; |
| import com.oracle.bmc.database.model.CreateAutonomousDatabaseDetails; |
| import com.oracle.bmc.database.model.GenerateAutonomousDatabaseWalletDetails; |
| import com.oracle.bmc.database.requests.CreateAutonomousDatabaseRequest; |
| import com.oracle.bmc.database.requests.GenerateAutonomousDatabaseWalletRequest; |
| import com.oracle.bmc.database.responses.CreateAutonomousDatabaseResponse; |
| import com.oracle.bmc.database.responses.GenerateAutonomousDatabaseWalletResponse; |
| import com.oracle.bmc.identity.Identity; |
| import com.oracle.bmc.identity.IdentityClient; |
| import com.oracle.bmc.identity.model.Tenancy; |
| import com.oracle.bmc.identity.requests.GetTenancyRequest; |
| import com.oracle.bmc.identity.responses.GetTenancyResponse; |
| import com.oracle.bmc.model.BmcException; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.lang.reflect.Method; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.Objects; |
| import java.util.Optional; |
| import java.util.zip.ZipEntry; |
| import java.util.zip.ZipInputStream; |
| import org.netbeans.modules.cloud.oracle.items.OCID; |
| import org.netbeans.modules.cloud.oracle.items.OCIItem; |
| import org.netbeans.modules.cloud.oracle.items.TenancyItem; |
| import org.openide.util.Exceptions; |
| import org.openide.util.Lookup; |
| import org.openide.util.NbBundle; |
| import org.openide.util.lookup.Lookups; |
| |
| /** |
| * Represents an OCI profile. A profile has a user, tenancy and region |
| * assigned. |
| */ |
| public final class OCIProfile implements OCISessionInitiator { |
| |
| /** |
| * ID of the default profile. |
| */ |
| public static final String DEFAULT_ID = "DEFAULT"; // NOI18N |
| /** |
| * Profile ID. |
| */ |
| private final String id; |
| /** |
| * Path to the profile's config file. |
| */ |
| private final Path configPath; |
| /** |
| * Timestamp of the config file at the time the profile has been initialized. |
| */ |
| private long fileStamp; |
| private ConfigFileAuthenticationDetailsProvider configProvider; |
| private IOException initError; |
| private Tenancy tenancyOpt; |
| |
| OCIProfile(Path configPath, String id) { |
| this(configPath, id, true); |
| init(); |
| } |
| |
| OCIProfile(Path configPath, String id, boolean internal) { |
| if (id == null) { |
| id = DEFAULT_ID; |
| } |
| if (configPath == null) { |
| configPath = OCIManager.getDefaultConfigPath(); |
| } |
| this.id = id; |
| this.configPath = configPath; |
| } |
| |
| /** |
| * Determines if the profile is defined by the default configuration file. |
| * @return true, if the profile comes from the default OCI configuration, false otherwise. |
| */ |
| public boolean isDefaultConfig() { |
| return configPath.equals(OCIManager.getDefaultConfigPath()); |
| } |
| |
| private void init() { |
| try { |
| if (!Files.exists(configPath)) { |
| return; |
| } |
| long stamp = Files.getLastModifiedTime(configPath).toMillis(); |
| String stringPath = configPath.toAbsolutePath().toString(); |
| ConfigFileReader.ConfigFile configFile = id == null ? ConfigFileReader.parse(stringPath) : ConfigFileReader.parse(stringPath, id); |
| configProvider = new ConfigFileAuthenticationDetailsProvider(configFile); |
| fileStamp = stamp; |
| } catch (IOException ex) { |
| initError = ex; |
| } catch (Throwable ex) { |
| initError = new IOException(ex); |
| } |
| } |
| |
| public Path getConfigPath() { |
| return configPath; |
| } |
| |
| public String getId() { |
| return id; |
| } |
| |
| public boolean isValid() { |
| return configProvider != null && fileStamp == configPath.toFile().lastModified(); // avoid IOE |
| } |
| |
| @Override |
| public BasicAuthenticationDetailsProvider getAuthenticationProvider() { |
| return configProvider; |
| } |
| |
| @Override |
| public Region getRegion() { |
| return configProvider.getRegion(); |
| } |
| |
| @Override |
| public String getTenantId() { |
| return configProvider == null ? null : configProvider.getTenantId(); |
| } |
| |
| public Tenancy getTenancyData() { |
| if (configProvider == null) { |
| return null; |
| } |
| synchronized (this) { |
| if (tenancyOpt != null || initError != null) { |
| return tenancyOpt; |
| } |
| } |
| try (final Identity identityClient = new IdentityClient(configProvider)) { |
| identityClient.setRegion(configProvider.getRegion()); |
| GetTenancyRequest gtr = GetTenancyRequest.builder().tenancyId(configProvider.getTenantId()).build(); |
| GetTenancyResponse response = identityClient.getTenancy(gtr); |
| Tenancy tenancy = response.getTenancy(); |
| synchronized (this) { |
| return tenancyOpt = tenancy; |
| } |
| } catch (Throwable t) { |
| initError = new IOException(t); |
| } |
| return null; |
| } |
| |
| /** |
| * Retrieves information about Tenancy configured in ~/.oci |
| * |
| * @return Optional {@code OCIItem} describing the Tenancy. If |
| * Optional.empty() OCI configuration was not found |
| */ |
| @NbBundle.Messages({ |
| "LBL_HomeRegion=Home Region: {0}" |
| }) |
| public Optional<TenancyItem> getTenancy() { |
| if (configProvider == null) { |
| return Optional.empty(); |
| } |
| synchronized (this) { |
| if (initError != null) { |
| return Optional.empty(); |
| } else if (tenancyOpt != null) { |
| return Optional.of(createTenancyItem(tenancyOpt)); |
| } |
| Tenancy t = getTenancyData(); |
| return t == null ? Optional.empty() : Optional.of(createTenancyItem(t)); |
| } |
| } |
| |
| /** |
| * Creates and initializes a new client. The client is authenticated by {@link #getAuthenticationProvider()} and |
| * its region is set from {@link #getRegion()}. Throws IllegalArgumentException when the client cannot be configured. |
| * |
| * @param <T> client type |
| * @param clientClass client class |
| * @return client instance. |
| */ |
| public <T> T newClient(Class<T> clientClass) { |
| try { |
| T client = clientClass.getConstructor(BasicAuthenticationDetailsProvider.class).newInstance(configProvider); |
| Method setRegion = clientClass.getMethod("setRegion", Region.class); |
| setRegion.invoke(client, configProvider.getRegion()); |
| return client; |
| } catch (ReflectiveOperationException ex) { |
| throw new IllegalArgumentException("Could not initialize client: " + clientClass); |
| } |
| } |
| |
| private TenancyItem createTenancyItem(Tenancy tenancy) { |
| TenancyItem item = new TenancyItem(OCID.of(tenancy.getId(), "Tenancy"), tenancy.getName()); |
| item.setDescription(Bundle.LBL_HomeRegion(tenancy.getHomeRegionKey())); |
| return item; |
| } |
| |
| private final Lookup lkp = Lookups.fixed(this); |
| |
| @Override |
| public Lookup getLookup() { |
| return lkp; |
| } |
| |
| public ConfigFileAuthenticationDetailsProvider getConfigProvider() { |
| return configProvider; |
| } |
| |
| /** |
| * Creates and downloads a wallet for the specified Autonomous Database. |
| * |
| * @param dbInstance Database identification |
| * @param password The password to encrypt the keys inside the wallet. The |
| * password must be at least 8 characters long and must include at least 1 |
| * letter and either 1 numeric character or 1 special character. |
| * @param parentPath Path where Database Wallet Directory will be created. |
| * @throws FileNotFoundException |
| * @throws IOException |
| */ |
| public Path downloadWallet(OCIItem dbInstance, String password, String parentPath) throws FileNotFoundException, IOException { |
| if (configProvider == null) { |
| return null; |
| } |
| try (final DatabaseClient client = new DatabaseClient(configProvider)) { |
| GenerateAutonomousDatabaseWalletDetails details = GenerateAutonomousDatabaseWalletDetails.builder().password(password).build(); |
| GenerateAutonomousDatabaseWalletRequest generateAutonomousDatabaseWalletRequest = GenerateAutonomousDatabaseWalletRequest.builder().autonomousDatabaseId(dbInstance.getKey().getValue()).generateAutonomousDatabaseWalletDetails(details).build(); |
| GenerateAutonomousDatabaseWalletResponse response = client.generateAutonomousDatabaseWallet(generateAutonomousDatabaseWalletRequest); |
| Path walletPath = null; |
| int i = 1; |
| do { |
| if (walletPath == null) { |
| walletPath = Paths.get(parentPath, dbInstance.getName()); |
| } else { |
| walletPath = Paths.get(parentPath, dbInstance.getName() + "_" + i++); //NOI18N |
| } |
| } while (Files.exists(walletPath)); |
| Files.createDirectory(walletPath); |
| ZipInputStream zin = new ZipInputStream(response.getInputStream()); |
| ZipEntry entry; |
| while ((entry = zin.getNextEntry()) != null) { |
| Path entryPath = walletPath.resolve(entry.getName()); |
| Files.copy(zin, entryPath); |
| } |
| return walletPath; |
| } |
| } |
| |
| /** |
| * Creates a new Autonomous Oracle Database. |
| * |
| * @param compartmentId Id of Compartment where the Database will be created |
| * @param dbName Name of Database |
| * @param password Password of ADMIN user |
| * @return true if DB was created |
| */ |
| public Optional<String> createAutonomousDatabase(String compartmentId, String dbName, char[] password) { |
| if (configProvider == null) { |
| return Optional.empty(); |
| } |
| try (final DatabaseClient client = new DatabaseClient(configProvider)) { |
| CreateAutonomousDatabaseBase createAutonomousDatabaseBase = CreateAutonomousDatabaseDetails.builder().compartmentId(compartmentId).dbName(dbName).adminPassword(new String(password)).cpuCoreCount(1).dataStorageSizeInTBs(1).build(); |
| CreateAutonomousDatabaseRequest createAutonomousDatabaseRequest = CreateAutonomousDatabaseRequest.builder().createAutonomousDatabaseDetails(createAutonomousDatabaseBase).build(); |
| try { |
| CreateAutonomousDatabaseResponse response = client.createAutonomousDatabase(createAutonomousDatabaseRequest); |
| } catch (BmcException e) { |
| return Optional.of(e.getMessage()); |
| } |
| return Optional.empty(); |
| } |
| } |
| |
| @Override |
| public int hashCode() { |
| int hash = 7; |
| hash = 19 * hash + Objects.hashCode(this.id); |
| hash = 19 * hash + Objects.hashCode(this.configPath); |
| return hash; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| if (obj == null) { |
| return false; |
| } |
| if (getClass() != obj.getClass()) { |
| return false; |
| } |
| final OCIProfile other = (OCIProfile) obj; |
| if (!Objects.equals(this.id, other.id)) { |
| return false; |
| } |
| return Objects.equals(this.configPath, other.configPath); |
| } |
| |
| |
| } |