com.microsoft.intellij.docker.utils.AzureDockerUIResources.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.intellij.docker.utils.AzureDockerUIResources.java

Source

/**
 * Copyright (c) Microsoft Corporation
 * <p/>
 * All rights reserved.
 * <p/>
 * MIT License
 * <p/>
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
 * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * <p/>
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
 * the Software.
 * <p/>
 * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
 * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.microsoft.intellij.docker.utils;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.ValidationInfo;
import com.jcraft.jsch.Session;
import com.microsoft.azure.docker.AzureDockerHostsManager;
import com.microsoft.azure.docker.model.AzureDockerCertVault;
import com.microsoft.azure.docker.model.AzureDockerImageInstance;
import com.microsoft.azure.docker.model.DockerHost;
import com.microsoft.azure.docker.model.EditableDockerHost;
import com.microsoft.azure.docker.ops.AzureDockerCertVaultOps;
import com.microsoft.azure.docker.ops.AzureDockerSSHOps;
import com.microsoft.azure.docker.ops.AzureDockerVMOps;
import com.microsoft.azure.docker.ops.utils.AzureDockerUtils;
import com.microsoft.azure.keyvault.KeyVaultClient;
import com.microsoft.azure.management.Azure;
import com.microsoft.azuretools.authmanage.AuthMethodManager;
import com.microsoft.azuretools.sdkmanage.AzureManager;
import com.microsoft.azuretools.telemetry.AppInsightsClient;
import com.microsoft.intellij.docker.dialogs.AzureInputDockerLoginCredsDialog;
import com.microsoft.intellij.docker.wizards.publish.AzureSelectDockerWizardDialog;
import com.microsoft.intellij.docker.wizards.publish.AzureSelectDockerWizardModel;
import com.microsoft.intellij.util.PluginUtil;
import com.microsoft.tooling.msservices.components.DefaultLoader;

import javax.swing.*;
import java.util.Date;

import static com.microsoft.intellij.ui.messages.AzureBundle.message;

public class AzureDockerUIResources {
    private static final Logger LOGGER = Logger.getInstance(AzureDockerUIResources.class);
    public static boolean CANCELED = false;

    public static void updateAzureResourcesWithProgressDialog(Project project) {
        ProgressManager.getInstance().run(new Task.Modal(project, "Loading Azure Resources", true) {
            @Override
            public void run(ProgressIndicator progressIndicator) {
                try {
                    progressIndicator.setFraction(.05);
                    AzureManager azureAuthManager = AuthMethodManager.getInstance().getAzureManager();

                    if (progressIndicator.isCanceled()) {
                        return;
                    }

                    // not signed in
                    if (azureAuthManager == null) {
                        return;
                    }

                    progressIndicator.setFraction(.1);
                    AzureDockerHostsManager dockerManager = AzureDockerHostsManager
                            .getAzureDockerHostsManagerEmpty(azureAuthManager);
                    if (progressIndicator.isCanceled()) {
                        return;
                    }

                    progressIndicator.setFraction(.2);
                    progressIndicator.setText2("Retrieving the subscription details...");
                    dockerManager.refreshDockerSubscriptions();
                    if (progressIndicator.isCanceled()) {
                        return;
                    }

                    progressIndicator.setFraction(.3);
                    progressIndicator.setText2("Retrieving the key vault...");
                    dockerManager.refreshDockerVaults();
                    if (progressIndicator.isCanceled()) {
                        return;
                    }

                    progressIndicator.setFraction(.45);
                    progressIndicator.setText2("Retrieving the key vault details...");
                    dockerManager.refreshDockerVaultDetails();
                    if (progressIndicator.isCanceled()) {
                        return;
                    }

                    progressIndicator.setFraction(.7);
                    progressIndicator.setText2("Retrieving the network details...");
                    dockerManager.refreshDockerVnetDetails();
                    if (progressIndicator.isCanceled()) {
                        return;
                    }

                    progressIndicator.setFraction(.8);
                    progressIndicator.setText2("Retrieving the storage account details...");
                    dockerManager.refreshDockerStorageAccountDetails();
                    if (progressIndicator.isCanceled()) {
                        return;
                    }

                    progressIndicator.setIndeterminate(true);
                    progressIndicator.setText2("Retrieving the Docker virtual machines details...");
                    dockerManager.refreshDockerHostDetails();
                    if (progressIndicator.isCanceled()) {
                        return;
                    }

                    CANCELED = false;
                    progressIndicator.setIndeterminate(true);

                } catch (Exception ex) {
                    ex.printStackTrace();
                    LOGGER.error("updateAzureResourcesWithProgressDialog", ex);
                    CANCELED = true;
                }
            }

            @Override
            public void onCancel() {
                CANCELED = true;
                super.onCancel();
            }
        });
    }

    /*
     * Opens a confirmation dialog box for the user to chose the delete action
     * @return integer representing the user's choise
     *  -1 - action was canceled
     *   0 - action was canceled
     *   1 - delete VM only
     *   2 - delete VM and associated resources (vnet, publicIp, nic, nsg)
     */

    public static int deleteAzureDockerHostConfirmationDialog(Azure azureClient, DockerHost dockerHost) {
        String promptMessageDeleteAll = String.format(
                "This operation will delete virtual machine %s and its resources:\n"
                        + "\t - network interface: %s\n" + "\t - public IP: %s\n" + "\t - virtual network: %s\n"
                        + "The associated disks and storage account will not be deleted\n",
                dockerHost.hostVM.name, dockerHost.hostVM.nicName, dockerHost.hostVM.publicIpName,
                dockerHost.hostVM.vnetName);

        String promptMessageDelete = String.format("This operation will delete virtual machine %s.\n"
                + "The associated disks and storage account will not be deleted\n\n"
                + "Are you sure you want to continue?\n", dockerHost.hostVM.name);

        String[] options;
        String promptMessage;

        if (AzureDockerVMOps.isDeletingDockerHostAllSafe(azureClient, dockerHost.hostVM.resourceGroupName,
                dockerHost.hostVM.name)) {
            promptMessage = promptMessageDeleteAll;
            options = new String[] { "Cancel", "Delete VM Only", "Delete All" };
        } else {
            promptMessage = promptMessageDelete;
            options = new String[] { "Cancel", "Delete" };
        }

        int dialogReturn = JOptionPane.showOptionDialog(null, promptMessage, "Delete Docker Host",
                JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, PluginUtil.getIcon("/icons/logwarn.png"),
                options, null);

        switch (dialogReturn) {
        case 0:
            if (AzureDockerUtils.DEBUG)
                System.out.format("Delete Docker Host op was canceled %s\n", dialogReturn);
            break;
        case 1:
            if (AzureDockerUtils.DEBUG)
                System.out.println("Delete VM only: " + dockerHost.name);
            break;
        case 2:
            if (AzureDockerUtils.DEBUG)
                System.out.println("Delete VM and resources: " + dockerHost.name);
            break;
        default:
            if (AzureDockerUtils.DEBUG)
                System.out.format("Delete Docker Host op was canceled %s\n", dialogReturn);
        }

        return dialogReturn;
    }

    public static void deleteDockerHost(Project project, Azure azureClient, DockerHost dockerHost, int option,
            Runnable runnable) {
        String progressMsg = (option == 2)
                ? String.format("Deleting Virtual Machine %s and Its Resources...", dockerHost.name)
                : String.format("Deleting Docker Host %s...", dockerHost.name);

        DefaultLoader.getIdeHelper().runInBackground(project, "Deleting Docker Host", false, true, progressMsg,
                new Runnable() {
                    @Override
                    public void run() {
                        try {
                            if (option == 2) {
                                AzureDockerVMOps.deleteDockerHostAll(azureClient,
                                        dockerHost.hostVM.resourceGroupName, dockerHost.hostVM.name);
                            } else {
                                AzureDockerVMOps.deleteDockerHost(azureClient, dockerHost.hostVM.resourceGroupName,
                                        dockerHost.hostVM.name);
                            }
                            DefaultLoader.getIdeHelper().runInBackground(project, "Updating Docker Hosts Details ",
                                    false, true, "Updating Docker hosts details...", new Runnable() {
                                        @Override
                                        public void run() {
                                            try {
                                                AzureDockerHostsManager dockerManager = AzureDockerHostsManager
                                                        .getAzureDockerHostsManagerEmpty(null);
                                                dockerManager.refreshDockerHostDetails();

                                                if (runnable != null) {
                                                    runnable.run();
                                                }
                                            } catch (Exception ee) {
                                                if (AzureDockerUtils.DEBUG)
                                                    ee.printStackTrace();
                                                LOGGER.error("onRemoveDockerHostAction", ee);
                                            }
                                        }
                                    });
                        } catch (Exception e) {
                            ApplicationManager.getApplication().invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    if (AzureDockerUtils.DEBUG)
                                        e.printStackTrace();
                                    LOGGER.error("onRemoveDockerHostAction", e);
                                    PluginUtil.displayErrorDialog("Delete Docker Host Error", String.format(
                                            "Unexpected error detected while deleting Docker host %s:\n\n%s",
                                            dockerHost.name, e.getMessage()));
                                }
                            });
                        }
                    }
                });
    }

    public static void publish2DockerHostContainer(Project project) {
        try {
            AzureDockerUIResources.CANCELED = false;

            AzureManager azureAuthManager = AuthMethodManager.getInstance().getAzureManager();
            // not signed in
            if (azureAuthManager == null) {
                System.out.println("ERROR! Not signed in!");
                return;
            }

            AzureDockerHostsManager dockerManager = AzureDockerHostsManager
                    .getAzureDockerHostsManagerEmpty(azureAuthManager);

            if (!dockerManager.isInitialized()) {
                AzureDockerUIResources.updateAzureResourcesWithProgressDialog(project);
                if (AzureDockerUIResources.CANCELED) {
                    return;
                }
            }

            DockerHost dockerHost = (dockerManager.getDockerPreferredSettings() != null)
                    ? dockerManager.getDockerHostForURL(dockerManager.getDockerPreferredSettings().dockerApiName)
                    : null;
            AzureDockerImageInstance dockerImageDescription = dockerManager
                    .getDefaultDockerImageDescription(project.getName(), dockerHost);

            AzureSelectDockerWizardModel model = new AzureSelectDockerWizardModel(project, dockerManager,
                    dockerImageDescription);
            AzureSelectDockerWizardDialog wizard = new AzureSelectDockerWizardDialog(model);
            if (dockerHost != null) {
                model.selectDefaultDockerHost(dockerHost, true);
            }
            wizard.show();

            if (wizard.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
                try {
                    String url = wizard.deploy();
                    if (AzureDockerUtils.DEBUG)
                        System.out.println("Web app published at: " + url);
                } catch (Exception ex) {
                    PluginUtil.displayErrorDialogAndLog(message("webAppDplyErr"), ex.getMessage(), ex);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static ValidationInfo validateComponent(String msgErr, JPanel panel, JComponent component,
            JComponent componentLabel) {
        panel.requestFocus();
        component.requestFocus();
        if (componentLabel != null) {
            componentLabel.setVisible(true);
        }
        panel.repaint();
        ValidationInfo info = new ValidationInfo(msgErr, component);
        return info;
    }

    public static void createDockerKeyVault(Project project, DockerHost dockerHost,
            AzureDockerHostsManager dockerManager) {
        if (dockerHost.certVault.hostName != null) {
            ProgressManager.getInstance().run(new Task.Backgroundable(project,
                    String.format("Creating Key Vault for %s...", dockerHost.name), true) {
                @Override
                public void run(ProgressIndicator progressIndicator) {
                    try {
                        progressIndicator.setFraction(.05);
                        progressIndicator.setText2(String
                                .format("Reading subscription details for Docker host %s ...", dockerHost.apiUrl));
                        Azure azureClient = dockerManager.getSubscriptionsMap().get(dockerHost.sid).azureClient;
                        KeyVaultClient keyVaultClient = dockerManager.getSubscriptionsMap()
                                .get(dockerHost.sid).keyVaultClient;
                        if (progressIndicator.isCanceled()) {
                            if (displayWarningOnCreateKeyVaultCancelAction() == 1) {
                                return;
                            }
                        }

                        String retryMsg = "Create";
                        int retries = 0;
                        AzureDockerCertVault certVault = null;
                        do {
                            progressIndicator.setFraction(.15 + .15 * retries);
                            progressIndicator.setText2(
                                    String.format("%s new key vault %s ...", retryMsg, dockerHost.certVault.name));
                            if (AzureDockerUtils.DEBUG)
                                System.out.println(retryMsg + " new Docker key vault: " + new Date().toString());
                            AzureDockerCertVaultOps.createOrUpdateVault(azureClient, dockerHost.certVault,
                                    keyVaultClient);
                            if (AzureDockerUtils.DEBUG)
                                System.out.println("Done creating new key vault: " + new Date().toString());
                            if (progressIndicator.isCanceled()) {
                                if (displayWarningOnCreateKeyVaultCancelAction() == 1) {
                                    return;
                                }
                            }
                            certVault = AzureDockerCertVaultOps.getVault(azureClient, dockerHost.certVault.name,
                                    dockerHost.certVault.resourceGroupName, keyVaultClient);
                            retries++;
                            retryMsg = "Retry creating";
                        } while (retries < 5 && (certVault == null || certVault.vmUsername == null)); // Retry couple times

                        progressIndicator.setFraction(.90);
                        progressIndicator.setText2("Updating key vaults ...");
                        if (AzureDockerUtils.DEBUG)
                            System.out.println("Refreshing key vaults: " + new Date().toString());
                        dockerManager.refreshDockerVaults();
                        dockerManager.refreshDockerVaultDetails();

                        if (AzureDockerUtils.DEBUG)
                            System.out.println("Done refreshing key vaults: " + new Date().toString());
                        if (progressIndicator.isCanceled()) {
                            if (displayWarningOnCreateKeyVaultCancelAction() == 1) {
                                return;
                            }
                        }

                        progressIndicator.setFraction(.90);
                        progressIndicator.setIndeterminate(true);

                    } catch (Exception e) {
                        String msg = "An error occurred while attempting to create Azure Key Vault for Docker host."
                                + "\n" + e.getMessage()
                                + "\n Try logging in using the automated path (create and use a service principal).\n";
                        LOGGER.error("Failed to Create Azure Key Vault", e);
                        PluginUtil.displayErrorDialogInAWTAndLog("Failed to Create Azure Key Vault", msg, e);
                    }
                }
            });

        }
    }

    private static int displayWarningOnCreateKeyVaultCancelAction() {
        return JOptionPane.showOptionDialog(null,
                "This action can leave the Docker virtual machine host in an partial setup state and which can cause publishing to a Docker container to fail!\n\n Are you sure you want this?",
                "Stop Create Azure Key Vault", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
                PluginUtil.getIcon("/icons/logwarn.png"), new String[] { "Cancel", "OK" }, null);
    }

    public static void updateDockerHost(Project project, EditableDockerHost editableDockerHost,
            AzureDockerHostsManager dockerManager, boolean doReset) {
        AppInsightsClient.createByType(AppInsightsClient.EventType.DockerHost, "", "Update");
        AzureInputDockerLoginCredsDialog loginCredsDialog = new AzureInputDockerLoginCredsDialog(project,
                editableDockerHost, dockerManager, doReset);
        loginCredsDialog.show();

        if (loginCredsDialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
            // Update Docker host log in credentials
            DockerHost updateHost = editableDockerHost.originalDockerHost;
            updateHost.isUpdating = true;
            DefaultLoader.getIdeHelper().runInBackground(project,
                    String.format("Updating %s Log In Credentials", updateHost.name), false, true,
                    String.format("Updating log in credentials for %s...", updateHost.name), new Runnable() {
                        @Override
                        public void run() {
                            try {
                                AzureDockerVMOps.updateDockerHostVM(
                                        dockerManager.getSubscriptionsMap().get(updateHost.sid).azureClient,
                                        editableDockerHost.updatedDockerHost);
                                updateHost.certVault = editableDockerHost.updatedDockerHost.certVault;
                                updateHost.hasPwdLogIn = editableDockerHost.updatedDockerHost.hasPwdLogIn;
                                updateHost.hasSSHLogIn = editableDockerHost.updatedDockerHost.hasSSHLogIn;
                                updateHost.hasKeyVault = false;
                                updateHost.certVault.uri = "";
                                updateHost.certVault.name = "";
                                Session session = AzureDockerSSHOps.createLoginInstance(updateHost);
                                AzureDockerVMOps.UpdateCurrentDockerUser(session);
                                updateHost.session = session;
                            } catch (Exception ee) {
                                if (AzureDockerUtils.DEBUG)
                                    ee.printStackTrace();
                                LOGGER.error("onEditDockerHostAction", ee);
                            }
                            updateHost.isUpdating = false;
                        }
                    });
        }

    }
}