sdedic commented on code in PR #6746: URL: https://github.com/apache/netbeans/pull/6746#discussion_r1407920382
########## java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/WorkspaceServiceImpl.java: ########## @@ -169,10 +169,41 @@ public final class WorkspaceServiceImpl implements WorkspaceService, LanguageCli private final LspServerState server; private NbCodeLanguageClient client; + /** + * List of workspace folders as reported by the client. Initialized in `initialize` request, + * and then updated by didChangeWorkspaceFolder notifications. + */ + private volatile List<FileObject> clientWorkspaceFolders = Collections.emptyList(); + WorkspaceServiceImpl(LspServerState server) { this.server = server; } + /** + * Returns the set of workspace folders reported by the client. If a folder from the list is recognized + * as a project, it will be also present in {@link #openedProjects()} including all its subprojects. + * The list of client workspace folders contains just toplevel items in client's workspace, as defined in + * LSP protocol. + * @return list of workspace folders + */ + public List<FileObject> getClientWorkspaceFolders() { + return new ArrayList<>(clientWorkspaceFolders); + } + + public void setClientWorkspaceFolders(List<WorkspaceFolder> clientWorkspaceFolders) { + this.clientWorkspaceFolders = new ArrayList<>(); + if (clientWorkspaceFolders == null) { + return; + } + try { Review Comment: If this is ever called from other place than client init, it will break thread consistency of the List. ########## enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/devops/DevopsProjectService.java: ########## @@ -0,0 +1,89 @@ +/* + * 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.devops; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import java.io.FileNotFoundException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.openide.filesystems.FileObject; +import org.openide.util.Exceptions; +import org.openide.util.Lookup; + +/** + * Finds OCI DevOps configuration if available. + * + * @author jhorvath + */ +public class DevopsProjectService { + private static DevopsConfigFinder finder = null; + + + public static List<String> getDevopsProjectOcid() { + List<FileObject> configs = getDefaultFinder().findDevopsConfig(); + Gson gson = new Gson(); + List<String> devopsOcid = new ArrayList<> (); + try { + for (FileObject config : configs) { + JsonObject json = gson.fromJson(new InputStreamReader(configs.get(0).getInputStream()), JsonObject.class); + JsonArray services = json.getAsJsonArray("cloudServices"); //NOI18N + for (JsonElement service : services) { + if ("oci".equals(service.getAsJsonObject().get("type").getAsString())) { //NOI18N + JsonObject data = service.getAsJsonObject().getAsJsonObject("data"); //NOI18N + JsonObject context = data.getAsJsonObject("context"); //NOI18N + devopsOcid.add(context.get("devopsProject").getAsString()); //NOI18N + } + } + } + } catch (FileNotFoundException ex) { + Exceptions.printStackTrace(ex); + } + return devopsOcid; + } + + + private static DevopsConfigFinder getDefaultFinder() { + if (finder == null) { + finder = Lookup.getDefault().lookup(DevopsConfigFinder.class); + } + if (finder == null) { + finder = new DefaultDevopsConfigFinder(); + } + return finder; + } + + public interface DevopsConfigFinder { + List<FileObject> findDevopsConfig(); + } + + public static class DefaultDevopsConfigFinder implements DevopsConfigFinder { Review Comment: nicpick: could be probably private / package-private. ########## enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/devops/DevopsProjectService.java: ########## @@ -0,0 +1,89 @@ +/* + * 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.devops; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import java.io.FileNotFoundException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.openide.filesystems.FileObject; +import org.openide.util.Exceptions; +import org.openide.util.Lookup; + +/** + * Finds OCI DevOps configuration if available. + * + * @author jhorvath + */ +public class DevopsProjectService { + private static DevopsConfigFinder finder = null; + + + public static List<String> getDevopsProjectOcid() { + List<FileObject> configs = getDefaultFinder().findDevopsConfig(); + Gson gson = new Gson(); + List<String> devopsOcid = new ArrayList<> (); + try { + for (FileObject config : configs) { + JsonObject json = gson.fromJson(new InputStreamReader(configs.get(0).getInputStream()), JsonObject.class); + JsonArray services = json.getAsJsonArray("cloudServices"); //NOI18N + for (JsonElement service : services) { + if ("oci".equals(service.getAsJsonObject().get("type").getAsString())) { //NOI18N Review Comment: I'd suggest checking for members existence. In the case the user damages the config, the impl should not NPE. ########## enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddDbConnectionToVault.java: ########## @@ -186,6 +214,7 @@ public void setValue(String selected) { for (OCIProfile profile : profiles) { Review Comment: nicpick: we generally avoid shadowing member variables except for constructor / setter parameters, for clarity. ########## enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddDbConnectionToVault.java: ########## @@ -629,17 +741,148 @@ private void addDbConnectionToVault(Result item) { .builder() .createSecretDetails(createDetails) .build(); - CreateSecretResponse response = client.createSecret(request); + client.createSecret(request); } } - } catch (BmcException e) { - NotifyDescriptor.Message msg = new NotifyDescriptor.Message(e.getMessage()); + // Add Vault to the ConfigMap artifact + DevopsClient devopsClient = DevopsClient.builder().build(OCIManager.getDefault().getActiveProfile().getConfigProvider()); + ListDeployArtifactsRequest request = ListDeployArtifactsRequest.builder() + .projectId(item.project.getKey().getValue()).build(); + ListDeployArtifactsResponse response = devopsClient.listDeployArtifacts(request); + List<DeployArtifactSummary> artifacts = response.getDeployArtifactCollection().getItems(); + boolean found = false; + for (DeployArtifactSummary artifact : artifacts) { + if ((item.project.getName() + "_oke_configmap").equals(artifact.getDisplayName())) { //NOI18N + h.progress("updating " + item.project.getName() + "_oke_configmap"); //NOI18N + found = true; + GetDeployArtifactRequest artRequest = GetDeployArtifactRequest.builder().deployArtifactId(artifact.getId()).build(); + GetDeployArtifactResponse artResponse = devopsClient.getDeployArtifact(artRequest); + DeployArtifactSource source = artResponse.getDeployArtifact().getDeployArtifactSource(); + if (source instanceof InlineDeployArtifactSource) { + byte[] content = ((InlineDeployArtifactSource) source).getBase64EncodedContent(); + String srcString = updateProperties(new String(content, StandardCharsets.UTF_8), + item.vault.getCompartmentId(), item.vault.getKey().getValue(), item.datasourceName); + byte[] base64Content = Base64.getEncoder().encode(srcString.getBytes(StandardCharsets.UTF_8)); + DeployArtifactSource updatedSource = InlineDeployArtifactSource.builder() + .base64EncodedContent(base64Content).build(); + UpdateDeployArtifactDetails updateArtifactDetails = UpdateDeployArtifactDetails.builder() + .deployArtifactSource(updatedSource) + .build(); + UpdateDeployArtifactRequest updateArtifactRequest = UpdateDeployArtifactRequest.builder() + .updateDeployArtifactDetails(updateArtifactDetails) + .deployArtifactId(artifact.getId()) + .build(); + devopsClient.updateDeployArtifact(updateArtifactRequest); + } + } + } + if (!found) { + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(Bundle.NoConfigMap(item.project.getName()), NotifyDescriptor.WARNING_MESSAGE); Review Comment: Will also display "Secrets created" - OK ? ########## enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddDbConnectionToVault.java: ########## @@ -629,17 +741,148 @@ private void addDbConnectionToVault(Result item) { .builder() .createSecretDetails(createDetails) .build(); - CreateSecretResponse response = client.createSecret(request); + client.createSecret(request); } } - } catch (BmcException e) { - NotifyDescriptor.Message msg = new NotifyDescriptor.Message(e.getMessage()); + // Add Vault to the ConfigMap artifact + DevopsClient devopsClient = DevopsClient.builder().build(OCIManager.getDefault().getActiveProfile().getConfigProvider()); + ListDeployArtifactsRequest request = ListDeployArtifactsRequest.builder() + .projectId(item.project.getKey().getValue()).build(); + ListDeployArtifactsResponse response = devopsClient.listDeployArtifacts(request); + List<DeployArtifactSummary> artifacts = response.getDeployArtifactCollection().getItems(); + boolean found = false; + for (DeployArtifactSummary artifact : artifacts) { + if ((item.project.getName() + "_oke_configmap").equals(artifact.getDisplayName())) { //NOI18N + h.progress("updating " + item.project.getName() + "_oke_configmap"); //NOI18N + found = true; + GetDeployArtifactRequest artRequest = GetDeployArtifactRequest.builder().deployArtifactId(artifact.getId()).build(); + GetDeployArtifactResponse artResponse = devopsClient.getDeployArtifact(artRequest); + DeployArtifactSource source = artResponse.getDeployArtifact().getDeployArtifactSource(); + if (source instanceof InlineDeployArtifactSource) { + byte[] content = ((InlineDeployArtifactSource) source).getBase64EncodedContent(); + String srcString = updateProperties(new String(content, StandardCharsets.UTF_8), + item.vault.getCompartmentId(), item.vault.getKey().getValue(), item.datasourceName); + byte[] base64Content = Base64.getEncoder().encode(srcString.getBytes(StandardCharsets.UTF_8)); + DeployArtifactSource updatedSource = InlineDeployArtifactSource.builder() + .base64EncodedContent(base64Content).build(); + UpdateDeployArtifactDetails updateArtifactDetails = UpdateDeployArtifactDetails.builder() + .deployArtifactSource(updatedSource) + .build(); + UpdateDeployArtifactRequest updateArtifactRequest = UpdateDeployArtifactRequest.builder() + .updateDeployArtifactDetails(updateArtifactDetails) + .deployArtifactId(artifact.getId()) + .build(); + devopsClient.updateDeployArtifact(updateArtifactRequest); + } + } + } + if (!found) { + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(Bundle.NoConfigMap(item.project.getName()), NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + } + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(Bundle.SecretsCreated()); DialogDisplayer.getDefault().notify(msg); - throw new RuntimeException(e); + } catch (Throwable e) { + h.finish(); + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(e.getMessage(), NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + Exceptions.printStackTrace(e); + } finally { + h.finish(); } - NotifyDescriptor.Message msg = new NotifyDescriptor.Message(Bundle.SecretsCreated()); - DialogDisplayer.getDefault().notify(msg); + } + + protected static String updateProperties(String configmap, String compartmentOcid, String vaultOcid, String datasourceName) { + StringWriter output = new StringWriter(); + String[] lines = configmap.split("\n"); + int previousIndent = 0; + Map<Integer, String> path = new LinkedHashMap<>(); + String propertiesName = null; + Map<String, String> properties = new LinkedHashMap<>(); + for (int i = 0; i < lines.length; i++) { + String line = lines[i]; + if (line.trim().startsWith("#") || line.isEmpty()) { + output.append(line); + output.append("\n"); + continue; + } + int indent = 0; + while (line.charAt(indent) == ' ') { + indent++; + } + if (previousIndent > indent || (propertiesName != null && !line.contains("="))) { + final int f = indent; + path.entrySet().removeIf(entry -> entry.getKey() >= f); + if (propertiesName != null) { + int propIndent = previousIndent; + if (properties.size() == 0) { + propIndent = indent + 2; + } + output.append( + formatProperties(propertiesName, properties, propIndent, compartmentOcid, vaultOcid, datasourceName)); + + properties.clear(); + } + propertiesName = null; + if (line.trim().equals("---")) { //NOI18N + output.append(line); + output.append("\n"); + continue; + } + } + if (propertiesName == null) { + String k = line.substring(0, line.indexOf(':')).trim(); + String v = line.substring(line.indexOf(':') + 1, line.length()).trim(); + if (k == null) { + throw new IllegalStateException(); + } + + path.put(indent, k); + output.append(line); + output.append("\n"); + if (v.trim().equals("|")) { + propertiesName = k; + continue; + } + } + if (propertiesName != null && line.contains("=")) { + properties.put(line.substring(0, line.indexOf('=')).trim(), + line.substring(line.indexOf('=') + 1, line.length()).trim()); + } + + previousIndent = indent; + } + output.append( + formatProperties(propertiesName, properties, previousIndent, compartmentOcid, vaultOcid, datasourceName)); + + return output.toString(); + } + + private static String formatProperties(String proprtiesName, Map<String, String> prop, int indent, String compartmentId, String vaultId, String datasourceName) { + StringBuilder output = new StringBuilder(); + if (proprtiesName.startsWith("bootstrap")) { // NOI18N + prop.entrySet().removeIf(entry -> ((String) entry.getKey()).startsWith("oci.vault.vaults")); // NOI18N + prop.put("oci.config.instance-principal.enabled", "true"); // NOI18N + prop.put("micronaut.config-client.enabled", "true"); // NOI18N + prop.put("oci.vault.config.enabled", "true"); // NOI18N + prop.put("oci.vault.vaults[0].ocid", vaultId); // NOI18N + prop.put("oci.vault.vaults[0].compartment-ocid", compartmentId); // NOI18N + } else if (proprtiesName.startsWith("application")) { // NOI18N + prop.put("datasources.default.dialect", "ORACLE"); // NOI18N + prop.put("datasources.default.ocid", "${DATASOURCES_" + datasourceName + "_OCID}"); // NOI18N + prop.put("datasources.default.walletPassword", "${DATASOURCES_" + datasourceName + "_WALLET_PASSWORD}"); // NOI18N + prop.put("datasources.default.username", "${DATASOURCES_" + datasourceName + "_USERNAME}"); // NOI18N + prop.put("datasources.default.password", "${DATASOURCES_" + datasourceName + "_PASSWORD}"); // NOI18N + } + for (Entry<String, String> entry : prop.entrySet()) { + output.append(new String(new char[indent]).replace('\0', ' ')); Review Comment: nice trick for JDK < 11 ! ########## java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/LspDevopsConfigFinder.java: ########## @@ -0,0 +1,49 @@ +/* + * 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.nbcode.integration; + +import java.util.ArrayList; +import java.util.List; +import org.netbeans.modules.cloud.oracle.devops.DevopsProjectService.DevopsConfigFinder; +import org.netbeans.modules.java.lsp.server.LspServerState; +import org.openide.filesystems.FileObject; +import org.openide.util.Lookup; +import org.openide.util.lookup.ServiceProvider; + +/** + * + * @author jhorvath + */ +@ServiceProvider(service = DevopsConfigFinder.class, position = 1000) +public class LspDevopsConfigFinder implements DevopsConfigFinder { + + @Override + public List<FileObject> findDevopsConfig() { + List<FileObject> folders = Lookup.getDefault().lookup(LspServerState.class).getClientWorkspaceFolders(); Review Comment: Just to be sure, please check `LspServerState` for `null` -- in some weird circumstances the context may get lost (i.e. a schedule through invokeLater or something like that). ########## enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddDbConnectionToVault.java: ########## @@ -528,31 +626,34 @@ private void showInput(Step step, NotifyDescriptor desc) { } } - NotifyDescriptor prepareInput(NotifyDescriptor.ComposedInput input, int number) { + @Override + public NotifyDescriptor createInput(NotifyDescriptor.ComposedInput input, int number) { if (number == 1) { - steps.get(0).prepare(null); - return steps.get(0).createInput(); - } - if (steps.size() > number) { + while (steps.size() > 1) { + steps.removeLast(); + } + steps.getLast().prepare(null); + } else if (lastNumber > number) { steps.removeLast(); + while(steps.getLast().onlyOneChoice() && steps.size() > 1) { Review Comment: really `> 1` and not `> nuber` ? ########## java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/LspDevopsConfigFinder.java: ########## @@ -0,0 +1,49 @@ +/* + * 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.nbcode.integration; + +import java.util.ArrayList; +import java.util.List; +import org.netbeans.modules.cloud.oracle.devops.DevopsProjectService.DevopsConfigFinder; +import org.netbeans.modules.java.lsp.server.LspServerState; +import org.openide.filesystems.FileObject; +import org.openide.util.Lookup; +import org.openide.util.lookup.ServiceProvider; + +/** + * + * @author jhorvath + */ +@ServiceProvider(service = DevopsConfigFinder.class, position = 1000) +public class LspDevopsConfigFinder implements DevopsConfigFinder { + + @Override + public List<FileObject> findDevopsConfig() { + List<FileObject> folders = Lookup.getDefault().lookup(LspServerState.class).getClientWorkspaceFolders(); + List<FileObject> result = new ArrayList<> (); + for (FileObject folder : folders) { + FileObject f = folder.getFileObject(".vscode/devops.json"); //NOI18N + if (f.isValid()) { Review Comment: null check, will NPE on a missing file. ########## enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddDbConnectionToVault.java: ########## @@ -491,12 +520,80 @@ public Result getValue() { return item; } } - + + class DevopsStep implements Step<Result, Result> { + + private Result item; + private Map<String, DevopsProjectItem> devopsProjects; Review Comment: suggest to document/comment that `devopsProjects` are keyed by project name; usually items are keyed by OCID. ########## enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddDbConnectionToVault.java: ########## @@ -528,31 +626,34 @@ private void showInput(Step step, NotifyDescriptor desc) { } } - NotifyDescriptor prepareInput(NotifyDescriptor.ComposedInput input, int number) { + @Override + public NotifyDescriptor createInput(NotifyDescriptor.ComposedInput input, int number) { if (number == 1) { - steps.get(0).prepare(null); - return steps.get(0).createInput(); - } - if (steps.size() > number) { + while (steps.size() > 1) { + steps.removeLast(); + } + steps.getLast().prepare(null); + } else if (lastNumber > number) { steps.removeLast(); + while(steps.getLast().onlyOneChoice() && steps.size() > 1) { + steps.removeLast(); + } + lastNumber = number; return steps.getLast().createInput(); + } else { + readValue(steps.getLast(), input.getInputs()[number - 2]); + steps.add(steps.getLast().getNext()); } - showInput(steps.getLast(), input.getInputs()[number - 2]); - Step currentStep = steps.getLast().getNext(); - if (currentStep == null) { - return null; + lastNumber = number; + + while(steps.getLast() != null && steps.getLast().onlyOneChoice()) { + steps.add(steps.getLast().getNext()); Review Comment: no `readValue` for steps added here - OK ? ########## enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddDbConnectionToVault.java: ########## @@ -629,17 +741,148 @@ private void addDbConnectionToVault(Result item) { .builder() .createSecretDetails(createDetails) .build(); - CreateSecretResponse response = client.createSecret(request); + client.createSecret(request); } } - } catch (BmcException e) { - NotifyDescriptor.Message msg = new NotifyDescriptor.Message(e.getMessage()); + // Add Vault to the ConfigMap artifact + DevopsClient devopsClient = DevopsClient.builder().build(OCIManager.getDefault().getActiveProfile().getConfigProvider()); + ListDeployArtifactsRequest request = ListDeployArtifactsRequest.builder() + .projectId(item.project.getKey().getValue()).build(); + ListDeployArtifactsResponse response = devopsClient.listDeployArtifacts(request); + List<DeployArtifactSummary> artifacts = response.getDeployArtifactCollection().getItems(); + boolean found = false; + for (DeployArtifactSummary artifact : artifacts) { + if ((item.project.getName() + "_oke_configmap").equals(artifact.getDisplayName())) { //NOI18N + h.progress("updating " + item.project.getName() + "_oke_configmap"); //NOI18N + found = true; + GetDeployArtifactRequest artRequest = GetDeployArtifactRequest.builder().deployArtifactId(artifact.getId()).build(); + GetDeployArtifactResponse artResponse = devopsClient.getDeployArtifact(artRequest); + DeployArtifactSource source = artResponse.getDeployArtifact().getDeployArtifactSource(); + if (source instanceof InlineDeployArtifactSource) { + byte[] content = ((InlineDeployArtifactSource) source).getBase64EncodedContent(); + String srcString = updateProperties(new String(content, StandardCharsets.UTF_8), + item.vault.getCompartmentId(), item.vault.getKey().getValue(), item.datasourceName); + byte[] base64Content = Base64.getEncoder().encode(srcString.getBytes(StandardCharsets.UTF_8)); + DeployArtifactSource updatedSource = InlineDeployArtifactSource.builder() + .base64EncodedContent(base64Content).build(); + UpdateDeployArtifactDetails updateArtifactDetails = UpdateDeployArtifactDetails.builder() + .deployArtifactSource(updatedSource) + .build(); + UpdateDeployArtifactRequest updateArtifactRequest = UpdateDeployArtifactRequest.builder() + .updateDeployArtifactDetails(updateArtifactDetails) + .deployArtifactId(artifact.getId()) + .build(); + devopsClient.updateDeployArtifact(updateArtifactRequest); + } + } + } + if (!found) { + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(Bundle.NoConfigMap(item.project.getName()), NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + } + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(Bundle.SecretsCreated()); DialogDisplayer.getDefault().notify(msg); - throw new RuntimeException(e); + } catch (Throwable e) { + h.finish(); + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(e.getMessage(), NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + Exceptions.printStackTrace(e); Review Comment: This would pop the dialog twice in IDE (once for `DialogDisplayer.notify()`, 2nd time for `printStackTrace`). If you still want to log, perhaps annotate the throwable with some small severity (?) ########## enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddDbConnectionToVault.java: ########## @@ -629,17 +741,148 @@ private void addDbConnectionToVault(Result item) { .builder() .createSecretDetails(createDetails) .build(); - CreateSecretResponse response = client.createSecret(request); + client.createSecret(request); } } - } catch (BmcException e) { - NotifyDescriptor.Message msg = new NotifyDescriptor.Message(e.getMessage()); + // Add Vault to the ConfigMap artifact + DevopsClient devopsClient = DevopsClient.builder().build(OCIManager.getDefault().getActiveProfile().getConfigProvider()); + ListDeployArtifactsRequest request = ListDeployArtifactsRequest.builder() + .projectId(item.project.getKey().getValue()).build(); + ListDeployArtifactsResponse response = devopsClient.listDeployArtifacts(request); + List<DeployArtifactSummary> artifacts = response.getDeployArtifactCollection().getItems(); + boolean found = false; + for (DeployArtifactSummary artifact : artifacts) { + if ((item.project.getName() + "_oke_configmap").equals(artifact.getDisplayName())) { //NOI18N + h.progress("updating " + item.project.getName() + "_oke_configmap"); //NOI18N + found = true; + GetDeployArtifactRequest artRequest = GetDeployArtifactRequest.builder().deployArtifactId(artifact.getId()).build(); + GetDeployArtifactResponse artResponse = devopsClient.getDeployArtifact(artRequest); + DeployArtifactSource source = artResponse.getDeployArtifact().getDeployArtifactSource(); + if (source instanceof InlineDeployArtifactSource) { + byte[] content = ((InlineDeployArtifactSource) source).getBase64EncodedContent(); + String srcString = updateProperties(new String(content, StandardCharsets.UTF_8), + item.vault.getCompartmentId(), item.vault.getKey().getValue(), item.datasourceName); + byte[] base64Content = Base64.getEncoder().encode(srcString.getBytes(StandardCharsets.UTF_8)); + DeployArtifactSource updatedSource = InlineDeployArtifactSource.builder() + .base64EncodedContent(base64Content).build(); + UpdateDeployArtifactDetails updateArtifactDetails = UpdateDeployArtifactDetails.builder() + .deployArtifactSource(updatedSource) + .build(); + UpdateDeployArtifactRequest updateArtifactRequest = UpdateDeployArtifactRequest.builder() + .updateDeployArtifactDetails(updateArtifactDetails) + .deployArtifactId(artifact.getId()) + .build(); + devopsClient.updateDeployArtifact(updateArtifactRequest); + } + } + } + if (!found) { + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(Bundle.NoConfigMap(item.project.getName()), NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + } + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(Bundle.SecretsCreated()); DialogDisplayer.getDefault().notify(msg); - throw new RuntimeException(e); + } catch (Throwable e) { + h.finish(); + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(e.getMessage(), NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + Exceptions.printStackTrace(e); + } finally { + h.finish(); } - NotifyDescriptor.Message msg = new NotifyDescriptor.Message(Bundle.SecretsCreated()); - DialogDisplayer.getDefault().notify(msg); + } + + protected static String updateProperties(String configmap, String compartmentOcid, String vaultOcid, String datasourceName) { + StringWriter output = new StringWriter(); + String[] lines = configmap.split("\n"); + int previousIndent = 0; + Map<Integer, String> path = new LinkedHashMap<>(); + String propertiesName = null; + Map<String, String> properties = new LinkedHashMap<>(); + for (int i = 0; i < lines.length; i++) { + String line = lines[i]; + if (line.trim().startsWith("#") || line.isEmpty()) { + output.append(line); + output.append("\n"); + continue; + } + int indent = 0; + while (line.charAt(indent) == ' ') { + indent++; + } + if (previousIndent > indent || (propertiesName != null && !line.contains("="))) { + final int f = indent; + path.entrySet().removeIf(entry -> entry.getKey() >= f); + if (propertiesName != null) { + int propIndent = previousIndent; + if (properties.size() == 0) { + propIndent = indent + 2; + } + output.append( + formatProperties(propertiesName, properties, propIndent, compartmentOcid, vaultOcid, datasourceName)); + + properties.clear(); + } + propertiesName = null; + if (line.trim().equals("---")) { //NOI18N + output.append(line); + output.append("\n"); + continue; + } + } + if (propertiesName == null) { + String k = line.substring(0, line.indexOf(':')).trim(); + String v = line.substring(line.indexOf(':') + 1, line.length()).trim(); + if (k == null) { + throw new IllegalStateException(); + } + + path.put(indent, k); + output.append(line); + output.append("\n"); + if (v.trim().equals("|")) { + propertiesName = k; + continue; + } + } + if (propertiesName != null && line.contains("=")) { + properties.put(line.substring(0, line.indexOf('=')).trim(), + line.substring(line.indexOf('=') + 1, line.length()).trim()); Review Comment: nitpck: unnecessary 2nd param to `substring` ########## enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddDbConnectionToVault.java: ########## @@ -629,17 +741,148 @@ private void addDbConnectionToVault(Result item) { .builder() .createSecretDetails(createDetails) .build(); - CreateSecretResponse response = client.createSecret(request); + client.createSecret(request); } } - } catch (BmcException e) { - NotifyDescriptor.Message msg = new NotifyDescriptor.Message(e.getMessage()); + // Add Vault to the ConfigMap artifact + DevopsClient devopsClient = DevopsClient.builder().build(OCIManager.getDefault().getActiveProfile().getConfigProvider()); + ListDeployArtifactsRequest request = ListDeployArtifactsRequest.builder() + .projectId(item.project.getKey().getValue()).build(); + ListDeployArtifactsResponse response = devopsClient.listDeployArtifacts(request); + List<DeployArtifactSummary> artifacts = response.getDeployArtifactCollection().getItems(); + boolean found = false; + for (DeployArtifactSummary artifact : artifacts) { + if ((item.project.getName() + "_oke_configmap").equals(artifact.getDisplayName())) { //NOI18N + h.progress("updating " + item.project.getName() + "_oke_configmap"); //NOI18N + found = true; + GetDeployArtifactRequest artRequest = GetDeployArtifactRequest.builder().deployArtifactId(artifact.getId()).build(); + GetDeployArtifactResponse artResponse = devopsClient.getDeployArtifact(artRequest); + DeployArtifactSource source = artResponse.getDeployArtifact().getDeployArtifactSource(); + if (source instanceof InlineDeployArtifactSource) { + byte[] content = ((InlineDeployArtifactSource) source).getBase64EncodedContent(); + String srcString = updateProperties(new String(content, StandardCharsets.UTF_8), + item.vault.getCompartmentId(), item.vault.getKey().getValue(), item.datasourceName); + byte[] base64Content = Base64.getEncoder().encode(srcString.getBytes(StandardCharsets.UTF_8)); + DeployArtifactSource updatedSource = InlineDeployArtifactSource.builder() + .base64EncodedContent(base64Content).build(); + UpdateDeployArtifactDetails updateArtifactDetails = UpdateDeployArtifactDetails.builder() + .deployArtifactSource(updatedSource) + .build(); + UpdateDeployArtifactRequest updateArtifactRequest = UpdateDeployArtifactRequest.builder() + .updateDeployArtifactDetails(updateArtifactDetails) + .deployArtifactId(artifact.getId()) + .build(); + devopsClient.updateDeployArtifact(updateArtifactRequest); + } + } + } + if (!found) { + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(Bundle.NoConfigMap(item.project.getName()), NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + } + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(Bundle.SecretsCreated()); DialogDisplayer.getDefault().notify(msg); - throw new RuntimeException(e); + } catch (Throwable e) { + h.finish(); + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(e.getMessage(), NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + Exceptions.printStackTrace(e); + } finally { + h.finish(); } - NotifyDescriptor.Message msg = new NotifyDescriptor.Message(Bundle.SecretsCreated()); - DialogDisplayer.getDefault().notify(msg); + } + + protected static String updateProperties(String configmap, String compartmentOcid, String vaultOcid, String datasourceName) { + StringWriter output = new StringWriter(); + String[] lines = configmap.split("\n"); + int previousIndent = 0; + Map<Integer, String> path = new LinkedHashMap<>(); + String propertiesName = null; + Map<String, String> properties = new LinkedHashMap<>(); + for (int i = 0; i < lines.length; i++) { + String line = lines[i]; + if (line.trim().startsWith("#") || line.isEmpty()) { + output.append(line); + output.append("\n"); + continue; + } + int indent = 0; + while (line.charAt(indent) == ' ') { + indent++; + } + if (previousIndent > indent || (propertiesName != null && !line.contains("="))) { + final int f = indent; + path.entrySet().removeIf(entry -> entry.getKey() >= f); + if (propertiesName != null) { + int propIndent = previousIndent; + if (properties.size() == 0) { + propIndent = indent + 2; + } + output.append( + formatProperties(propertiesName, properties, propIndent, compartmentOcid, vaultOcid, datasourceName)); + + properties.clear(); + } + propertiesName = null; + if (line.trim().equals("---")) { //NOI18N + output.append(line); + output.append("\n"); + continue; + } + } + if (propertiesName == null) { + String k = line.substring(0, line.indexOf(':')).trim(); Review Comment: I think it will fail with exception if the line does not contain ':'. ########## enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/actions/AddDbConnectionToVault.java: ########## @@ -629,17 +741,148 @@ private void addDbConnectionToVault(Result item) { .builder() .createSecretDetails(createDetails) .build(); - CreateSecretResponse response = client.createSecret(request); + client.createSecret(request); } } - } catch (BmcException e) { - NotifyDescriptor.Message msg = new NotifyDescriptor.Message(e.getMessage()); + // Add Vault to the ConfigMap artifact + DevopsClient devopsClient = DevopsClient.builder().build(OCIManager.getDefault().getActiveProfile().getConfigProvider()); + ListDeployArtifactsRequest request = ListDeployArtifactsRequest.builder() + .projectId(item.project.getKey().getValue()).build(); + ListDeployArtifactsResponse response = devopsClient.listDeployArtifacts(request); + List<DeployArtifactSummary> artifacts = response.getDeployArtifactCollection().getItems(); + boolean found = false; + for (DeployArtifactSummary artifact : artifacts) { + if ((item.project.getName() + "_oke_configmap").equals(artifact.getDisplayName())) { //NOI18N + h.progress("updating " + item.project.getName() + "_oke_configmap"); //NOI18N + found = true; + GetDeployArtifactRequest artRequest = GetDeployArtifactRequest.builder().deployArtifactId(artifact.getId()).build(); + GetDeployArtifactResponse artResponse = devopsClient.getDeployArtifact(artRequest); + DeployArtifactSource source = artResponse.getDeployArtifact().getDeployArtifactSource(); + if (source instanceof InlineDeployArtifactSource) { + byte[] content = ((InlineDeployArtifactSource) source).getBase64EncodedContent(); + String srcString = updateProperties(new String(content, StandardCharsets.UTF_8), + item.vault.getCompartmentId(), item.vault.getKey().getValue(), item.datasourceName); + byte[] base64Content = Base64.getEncoder().encode(srcString.getBytes(StandardCharsets.UTF_8)); + DeployArtifactSource updatedSource = InlineDeployArtifactSource.builder() + .base64EncodedContent(base64Content).build(); + UpdateDeployArtifactDetails updateArtifactDetails = UpdateDeployArtifactDetails.builder() + .deployArtifactSource(updatedSource) + .build(); + UpdateDeployArtifactRequest updateArtifactRequest = UpdateDeployArtifactRequest.builder() + .updateDeployArtifactDetails(updateArtifactDetails) + .deployArtifactId(artifact.getId()) + .build(); + devopsClient.updateDeployArtifact(updateArtifactRequest); + } + } + } + if (!found) { + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(Bundle.NoConfigMap(item.project.getName()), NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(msg); + } + NotifyDescriptor.Message msg = new NotifyDescriptor.Message(Bundle.SecretsCreated()); DialogDisplayer.getDefault().notify(msg); - throw new RuntimeException(e); + } catch (Throwable e) { Review Comment: catch `ThreadDeath` and rethrow. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: notifications-unsubscr...@netbeans.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@netbeans.apache.org For additional commands, e-mail: notifications-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists