From 2bb8806da6050574bee7eaf8b3f12c2919b2a92b Mon Sep 17 00:00:00 2001 From: Alan Ren Date: Mon, 5 Aug 2019 16:01:34 -0700 Subject: [PATCH] dialog assisted notebooks (#6564) --- .../notebooks/bdc/2019/deploy-bdc-aks.ipynb | 202 ++++++++++++-- .../bdc/2019/deploy-bdc-existing-aks.ipynb | 249 ++++++++++++++++++ .../2019/deploy-bdc-existing-cluster.ipynb | 142 ---------- .../docker/2017/deploy-sql2017-image.ipynb | 100 ++++++- .../docker/2019/deploy-sql2019-image.ipynb | 102 ++++++- extensions/resource-deployment/package.json | 220 +++++++++++++++- .../resource-deployment/package.nls.json | 27 +- .../resource-deployment/src/interfaces.ts | 42 ++- extensions/resource-deployment/src/main.ts | 6 +- .../src/services/notebookService.ts | 2 +- .../src/ui/deploymentDialog.ts | 135 ++++++++++ .../resource-deployment/src/ui/dialogBase.ts | 33 +++ .../src/ui/resourceDeploymentDialog.ts | 39 ++- 13 files changed, 1074 insertions(+), 225 deletions(-) create mode 100644 extensions/resource-deployment/notebooks/bdc/2019/deploy-bdc-existing-aks.ipynb delete mode 100644 extensions/resource-deployment/notebooks/bdc/2019/deploy-bdc-existing-cluster.ipynb create mode 100644 extensions/resource-deployment/src/ui/deploymentDialog.ts create mode 100644 extensions/resource-deployment/src/ui/dialogBase.ts diff --git a/extensions/resource-deployment/notebooks/bdc/2019/deploy-bdc-aks.ipynb b/extensions/resource-deployment/notebooks/bdc/2019/deploy-bdc-aks.ipynb index bada60714b..9930ea0dc4 100644 --- a/extensions/resource-deployment/notebooks/bdc/2019/deploy-bdc-aks.ipynb +++ b/extensions/resource-deployment/notebooks/bdc/2019/deploy-bdc-aks.ipynb @@ -6,7 +6,7 @@ }, "language_info": { "name": "python", - "version": "3.6.6", + "version": "3.7.3", "mimetype": "text/x-python", "codemirror_mode": { "name": "ipython", @@ -22,12 +22,33 @@ "cells": [ { "cell_type": "markdown", - "source": "![Microsoft](https://raw.githubusercontent.com/microsoft/azuredatastudio/master/src/sql/media/microsoft-small-logo.png)\n \n## Create Azure Kubernetes Service cluster and deploy SQL Server 2019 CTP 3.2 big data cluster\n \nThis notebook walks through the process of creating a new Azure Kubernetes Service cluster first, and then deploys a SQL Server 2019 CTP 3.2 big data cluster on the newly created AKS cluster.\n \n* Follow the instructions in the **Prerequisites** cell to install the tools if not already installed.\n* The **Required information** cell will prompt you for a password that will be used to access the cluster controller, SQL Server, and Knox.\n* The values in the **Azure settings** and **Default settings** cell can be changed as appropriate.", + "source": [ + "![Microsoft](https://raw.githubusercontent.com/microsoft/azuredatastudio/master/src/sql/media/microsoft-small-logo.png)\n", + " \n", + "## Create Azure Kubernetes Service cluster and deploy SQL Server 2019 CTP 3.2 big data cluster\n", + " \n", + "This notebook walks through the process of creating a new Azure Kubernetes Service cluster first, and then deploys a SQL Server 2019 CTP 3.2 big data cluster on the newly created AKS cluster.\n", + " \n", + "* Follow the instructions in the **Prerequisites** cell to install the tools if not already installed.\n", + "* The **Required information** cell will prompt you for a password that will be used to access the cluster controller, SQL Server, and Knox.\n", + "* The values in the **Azure settings** and **Default settings** cell can be changed as appropriate.\n", + "\n", + "Please press the \"Run Cells\" button to run the notebook" + ], "metadata": {} }, { "cell_type": "markdown", - "source": "### **Prerequisites**\nEnsure the following tools are installed and added to PATH before proceeding.\n\n|Tools|Description|Installation|\n|---|---|---|\n| Azure CLI |Command-line tool for managing Azure services. Used to create AKS cluster | [Installation](https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest) |\n|kubectl | Command-line tool for monitoring the underlying Kuberentes cluster | [Installation](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-binary-using-native-package-management) |\n|azdata | Command-line tool for installing and managing a big data cluster |[Installation](https://docs.microsoft.com/en-us/sql/big-data-cluster/deploy-install-azdata?view=sqlallproducts-allversions) |", + "source": [ + "### **Prerequisites**\n", + "Ensure the following tools are installed and added to PATH before proceeding.\n", + "\n", + "|Tools|Description|Installation|\n", + "|---|---|---|\n", + "|Azure CLI |Command-line tool for managing Azure services. Used to create AKS cluster | [Installation](https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest) |\n", + "|kubectl | Command-line tool for monitoring the underlying Kuberentes cluster | [Installation](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-binary-using-native-package-management) |\n", + "|azdata | Command-line tool for installing and managing a big data cluster |[Installation](https://docs.microsoft.com/en-us/sql/big-data-cluster/deploy-install-azdata?view=sqlallproducts-allversions) |" + ], "metadata": {} }, { @@ -37,7 +58,29 @@ }, { "cell_type": "code", - "source": "import sys\r\ndef run_command():\r\n print(\"Executing: \" + cmd)\r\n !{cmd}\r\n if _exit_code != 0:\r\n sys.exit(f'Command execution failed with exit code: {str(_exit_code)}.\\n\\t{cmd}\\n')\r\n print(f'Successfully executed: {cmd}')\r\n\r\ncmd = 'az --version'\r\nrun_command()\r\ncmd = 'kubectl version --client=true'\r\nrun_command()\r\ncmd = 'azdata --version'\r\nrun_command()", + "source": [ + "import pandas,sys,os,getpass,time,json,html\r\n", + "pandas_version = pandas.__version__.split('.')\r\n", + "pandas_major = int(pandas_version[0])\r\n", + "pandas_minor = int(pandas_version[1])\r\n", + "pandas_patch = int(pandas_version[2])\r\n", + "if not (pandas_major > 0 or (pandas_major == 0 and pandas_minor > 24) or (pandas_major == 0 and pandas_minor == 24 and pandas_patch >= 2)):\r\n", + " sys.exit('Please upgrade the Notebook dependency before you can proceed, you can do it by running the \"Reinstall Notebook dependencies\" command in Azure Data Studio.')\r\n", + "\r\n", + "def run_command():\r\n", + " print(\"Executing: \" + cmd)\r\n", + " !{cmd}\r\n", + " if _exit_code != 0:\r\n", + " sys.exit(f'Command execution failed with exit code: {str(_exit_code)}.\\n\\t{cmd}\\n')\r\n", + " print(f'Successfully executed: {cmd}')\r\n", + "\r\n", + "cmd = 'az --version'\r\n", + "run_command()\r\n", + "cmd = 'kubectl version --client=true'\r\n", + "run_command()\r\n", + "cmd = 'azdata --version'\r\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 1 @@ -49,19 +92,49 @@ }, { "cell_type": "code", - "source": "import getpass\nmssql_password = getpass.getpass(prompt = 'SQL Server 2019 big data cluster controller password')\nif mssql_password == \"\":\n sys.exit(f'Password is required')\nconfirm_password = getpass.getpass(prompt = 'Confirm password')\nif mssql_password != confirm_password:\n sys.exit(f'Passwords do not match.')\nprint('Password accepted, you can also use the same password to access Knox and SQL Server.')", + "source": [ + "env_var_flag = \"AZDATA_NB_VAR_BDC_CONTROLLER_PASSWORD\" in os.environ\n", + "if env_var_flag:\n", + " mssql_password = os.environ[\"AZDATA_NB_VAR_BDC_CONTROLLER_PASSWORD\"]\n", + "else: \n", + " mssql_password = getpass.getpass(prompt = 'SQL Server 2019 big data cluster controller password')\n", + " if mssql_password == \"\":\n", + " sys.exit(f'Password is required.')\n", + " confirm_password = getpass.getpass(prompt = 'Confirm password')\n", + " if mssql_password != confirm_password:\n", + " sys.exit(f'Passwords do not match.')\n", + "print('Password accepted, you can also use the same password to access Knox and SQL Server.')" + ], "metadata": {}, "outputs": [], "execution_count": 2 }, { "cell_type": "markdown", - "source": "### **Azure settings**\n*Subscription ID*: visit here to find out the subscriptions you can use, if you leave it unspecified, the default subscription will be used.\n\n*VM Size*: visit here to find out the available VM sizes you could use. \n \n*Region*: visit here to find out the Azure regions where the Azure Kubernettes Service is available.", + "source": [ + "### **Azure settings**\n", + "*Subscription ID*: visit here to find out the subscriptions you can use, if you leave it unspecified, the default subscription will be used.\n", + "\n", + "*VM Size*: visit here to find out the available VM sizes you could use. \n", + " \n", + "*Region*: visit here to find out the Azure regions where the Azure Kubernettes Service is available." + ], "metadata": {} }, { "cell_type": "code", - "source": "azure_subscription_id = \"\"\nazure_vm_size = \"Standard_E4s_v3\"\nazure_region = \"eastus\"\nazure_vm_count = int(5)", + "source": [ + "if env_var_flag:\n", + " azure_subscription_id = os.environ[\"AZDATA_NB_VAR_BDC_AZURE_SUBSCRIPTION\"]\n", + " azure_vm_size = os.environ[\"AZDATA_NB_VAR_BDC_AZURE_VM_SIZE\"]\n", + " azure_region = os.environ[\"AZDATA_NB_VAR_BDC_AZURE_REGION\"]\n", + " azure_vm_count = int(os.environ[\"AZDATA_NB_VAR_BDC_VM_COUNT\"])\n", + "else:\n", + " azure_subscription_id = \"\"\n", + " azure_vm_size = \"Standard_E4s_v3\"\n", + " azure_region = \"eastus\"\n", + " azure_vm_count = int(5)" + ], "metadata": {}, "outputs": [], "execution_count": 3 @@ -73,31 +146,73 @@ }, { "cell_type": "code", - "source": "import time\nmssql_cluster_name = 'mssql-cluster'\nmssql_controller_username = 'admin'\nazure_resource_group = mssql_cluster_name + '-' + time.strftime(\"%Y%m%d%H%M%S\", time.localtime())\naks_cluster_name = azure_resource_group\nconfiguration_profile = 'aks-dev-test'\nconfiguration_folder = 'mssql-bdc-configuration'\nprint(f'Azure subscription: {azure_subscription_id}')\nprint(f'Azure VM size: {azure_vm_size}')\nprint(f'Azure VM count: {str(azure_vm_count)}')\nprint(f'Azure region: {azure_region}')\nprint(f'Azure resource group: {azure_resource_group}')\nprint(f'AKS cluster name: {aks_cluster_name}')\nprint(f'SQL Server big data cluster name: {mssql_cluster_name}')\nprint(f'SQL Server big data cluster controller user name: {mssql_controller_username}')\nprint(f'Deployment configuration profile: {configuration_profile}')\nprint(f'Deployment configuration: {configuration_folder}')", + "source": [ + "if env_var_flag:\n", + " mssql_cluster_name = os.environ[\"AZDATA_NB_VAR_BDC_NAME\"]\n", + " mssql_controller_username = os.environ[\"AZDATA_NB_VAR_BDC_CONTROLLER_USERNAME\"]\n", + " azure_resource_group = os.environ[\"AZDATA_NB_VAR_BDC_RESOURCEGROUP_NAME\"]\n", + " aks_cluster_name = os.environ[\"AZDATA_NB_VAR_BDC_AKS_NAME\"]\n", + "else:\n", + " mssql_cluster_name = 'mssql-cluster'\n", + " mssql_controller_username = 'admin'\n", + " azure_resource_group = mssql_cluster_name + '-' + time.strftime(\"%Y%m%d%H%M%S\", time.localtime())\n", + " aks_cluster_name = azure_resource_group\n", + "configuration_profile = 'aks-dev-test'\n", + "configuration_folder = 'mssql-bdc-configuration'\n", + "print(f'Azure subscription: {azure_subscription_id}')\n", + "print(f'Azure VM size: {azure_vm_size}')\n", + "print(f'Azure VM count: {str(azure_vm_count)}')\n", + "print(f'Azure region: {azure_region}')\n", + "print(f'Azure resource group: {azure_resource_group}')\n", + "print(f'AKS cluster name: {aks_cluster_name}')\n", + "print(f'SQL Server big data cluster name: {mssql_cluster_name}')\n", + "print(f'SQL Server big data cluster controller user name: {mssql_controller_username}')\n", + "print(f'Deployment configuration profile: {configuration_profile}')\n", + "print(f'Deployment configuration: {configuration_folder}')" + ], "metadata": {}, "outputs": [], "execution_count": 4 }, { "cell_type": "markdown", - "source": "### **Login to Azure**\n\nThis will open a web browser window to enable credentials to be entered. If this cells is hanging forever, it might be because your Web browser windows is waiting for you to enter your Azure credentials!\n", + "source": [ + "### **Login to Azure**\n", + "\n", + "This will open a web browser window to enable credentials to be entered. If this cells is hanging forever, it might be because your Web browser windows is waiting for you to enter your Azure credentials!\n", + "" + ], "metadata": {} }, { "cell_type": "code", - "source": "cmd = f'az login'\nrun_command()", + "source": [ + "cmd = f'az login'\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 5 }, { "cell_type": "markdown", - "source": "\n### **Set active Azure subscription**", + "source": [ + "\n", + "### **Set active Azure subscription**" + ], "metadata": {} }, { "cell_type": "code", - "source": "if azure_subscription_id != \"\":\n cmd = f'az account set --subscription {azure_subscription_id}'\n run_command()\nelse:\n print('Using the default Azure subscription', {azure_subscription_id})\ncmd = f'az account show'\nrun_command()", + "source": [ + "if azure_subscription_id != \"\":\n", + " cmd = f'az account set --subscription {azure_subscription_id}'\n", + " run_command()\n", + "else:\n", + " print('Using the default Azure subscription', {azure_subscription_id})\n", + "cmd = f'az account show'\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 6 @@ -109,7 +224,10 @@ }, { "cell_type": "code", - "source": "cmd = f'az group create --name {azure_resource_group} --location {azure_region}'\nrun_command()", + "source": [ + "cmd = f'az group create --name {azure_resource_group} --location {azure_region}'\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 7 @@ -121,7 +239,10 @@ }, { "cell_type": "code", - "source": "cmd = f'az aks create --name {aks_cluster_name} --resource-group {azure_resource_group} --generate-ssh-keys --node-vm-size {azure_vm_size} --node-count {azure_vm_count}' \nrun_command()", + "source": [ + "cmd = f'az aks create --name {aks_cluster_name} --resource-group {azure_resource_group} --generate-ssh-keys --node-vm-size {azure_vm_size} --node-count {azure_vm_count}' \n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 8 @@ -133,7 +254,10 @@ }, { "cell_type": "code", - "source": "cmd = f'az aks get-credentials --resource-group {azure_resource_group} --name {aks_cluster_name} --admin --overwrite-existing'\r\nrun_command()", + "source": [ + "cmd = f'az aks get-credentials --resource-group {azure_resource_group} --name {aks_cluster_name} --admin --overwrite-existing'\r\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 9 @@ -145,7 +269,13 @@ }, { "cell_type": "code", - "source": "import os\nos.environ[\"ACCEPT_EULA\"] = 'yes'\ncmd = f'azdata bdc config init --source {configuration_profile} --target {configuration_folder} --force'\nrun_command()\ncmd = f'azdata bdc config replace -c {configuration_folder}/cluster.json -j metadata.name={mssql_cluster_name}'\nrun_command()", + "source": [ + "os.environ[\"ACCEPT_EULA\"] = 'yes'\n", + "cmd = f'azdata bdc config init --source {configuration_profile} --target {configuration_folder} --force'\n", + "run_command()\n", + "cmd = f'azdata bdc config replace -c {configuration_folder}/cluster.json -j metadata.name={mssql_cluster_name}'\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 10 @@ -157,7 +287,15 @@ }, { "cell_type": "code", - "source": "print (f'Creating SQL Server 2019 big data cluster: {mssql_cluster_name} using configuration {configuration_folder}')\nos.environ[\"CONTROLLER_USERNAME\"] = mssql_controller_username\nos.environ[\"CONTROLLER_PASSWORD\"] = mssql_password\nos.environ[\"MSSQL_SA_PASSWORD\"] = mssql_password\nos.environ[\"KNOX_PASSWORD\"] = mssql_password\ncmd = f'azdata bdc create -c {configuration_folder}'\nrun_command()", + "source": [ + "print (f'Creating SQL Server 2019 big data cluster: {mssql_cluster_name} using configuration {configuration_folder}')\n", + "os.environ[\"CONTROLLER_USERNAME\"] = mssql_controller_username\n", + "os.environ[\"CONTROLLER_PASSWORD\"] = mssql_password\n", + "os.environ[\"MSSQL_SA_PASSWORD\"] = mssql_password\n", + "os.environ[\"KNOX_PASSWORD\"] = mssql_password\n", + "cmd = f'azdata bdc create -c {configuration_folder}'\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 11 @@ -169,7 +307,10 @@ }, { "cell_type": "code", - "source": "cmd = f'azdata login --cluster-name {mssql_cluster_name}'\nrun_command()", + "source": [ + "cmd = f'azdata login --cluster-name {mssql_cluster_name}'\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 12 @@ -181,19 +322,38 @@ }, { "cell_type": "code", - "source": "import json,html,pandas\nfrom IPython.display import *\npandas.set_option('display.max_colwidth', -1)\ncmd = f'azdata bdc endpoint list'\ncmdOutput = !{cmd}\nendpoints = json.loads(''.join(cmdOutput))\nendpointsDataFrame = pandas.DataFrame(endpoints)\nendpointsDataFrame.columns = [' '.join(word[0].upper() + word[1:] for word in columnName.split()) for columnName in endpoints[0].keys()]\ndisplay(HTML(endpointsDataFrame.to_html(index=False, render_links=True)))", + "source": [ + "from IPython.display import *\n", + "pandas.set_option('display.max_colwidth', -1)\n", + "cmd = f'azdata bdc endpoint list'\n", + "cmdOutput = !{cmd}\n", + "endpoints = json.loads(''.join(cmdOutput))\n", + "endpointsDataFrame = pandas.DataFrame(endpoints)\n", + "endpointsDataFrame.columns = [' '.join(word[0].upper() + word[1:] for word in columnName.split()) for columnName in endpoints[0].keys()]\n", + "display(HTML(endpointsDataFrame.to_html(index=False, render_links=True)))" + ], "metadata": {}, "outputs": [], "execution_count": 13 }, { "cell_type": "markdown", - "source": "### **Connect to master SQL Server instance in Azure Data Studio**\r\nClick the link below to connect to the master SQL Server instance of the SQL Server 2019 big data cluster.", + "source": [ + "### **Connect to master SQL Server instance in Azure Data Studio**\r\n", + "Click the link below to connect to the master SQL Server instance of the SQL Server 2019 big data cluster." + ], "metadata": {} }, { "cell_type": "code", - "source": "sqlEndpoints = [x for x in endpoints if x['name'] == 'sql-server-master']\r\nif sqlEndpoints and len(sqlEndpoints) == 1:\r\n connectionParameter = '{\"serverName\":\"' + sqlEndpoints[0]['endpoint'] + '\",\"providerName\":\"MSSQL\",\"authenticationType\":\"SqlLogin\",\"userName\":\"sa\",\"password\":' + json.dumps(mssql_password) + '}'\r\n display(HTML('
Click here to connect to master SQL Server instance
'))\r\nelse:\r\n sys.exit('Could not find the master SQL Server instance endpoint')", + "source": [ + "sqlEndpoints = [x for x in endpoints if x['name'] == 'sql-server-master']\r\n", + "if sqlEndpoints and len(sqlEndpoints) == 1:\r\n", + " connectionParameter = '{\"serverName\":\"' + sqlEndpoints[0]['endpoint'] + '\",\"providerName\":\"MSSQL\",\"authenticationType\":\"SqlLogin\",\"userName\":\"sa\",\"password\":' + json.dumps(mssql_password) + '}'\r\n", + " display(HTML('
Click here to connect to master SQL Server instance
'))\r\n", + "else:\r\n", + " sys.exit('Could not find the master SQL Server instance endpoint.')" + ], "metadata": {}, "outputs": [], "execution_count": 14 diff --git a/extensions/resource-deployment/notebooks/bdc/2019/deploy-bdc-existing-aks.ipynb b/extensions/resource-deployment/notebooks/bdc/2019/deploy-bdc-existing-aks.ipynb new file mode 100644 index 0000000000..b7e8999e71 --- /dev/null +++ b/extensions/resource-deployment/notebooks/bdc/2019/deploy-bdc-existing-aks.ipynb @@ -0,0 +1,249 @@ +{ + "metadata": { + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python", + "version": "3.7.3", + "mimetype": "text/x-python", + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "pygments_lexer": "ipython3", + "nbconvert_exporter": "python", + "file_extension": ".py" + } + }, + "nbformat_minor": 2, + "nbformat": 4, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "![Microsoft](https://raw.githubusercontent.com/microsoft/azuredatastudio/master/src/sql/media/microsoft-small-logo.png)\n", + " \n", + "## Deploy SQL Server 2019 CTP 3.2 big data cluster on an existing Azure Kubernetes Service (AKS) cluster\n", + " \n", + "This notebook walks through the process of deploying a SQL Server 2019 CTP 3.2 big data cluster on an existing AKS cluster.\n", + " \n", + "* Follow the instructions in the **Prerequisites** cell to install the tools if not already installed.\n", + "* Make sure you have the target cluster set as the current context in your kubectl config file.\n", + " The config file would typically be under C:\\Users\\(userid)\\.kube on Windows, and under ~/.kube/ for macOS and Linux for a default installation.\n", + " In the kubectl config file, look for \"current-context\" and ensure it is set to the AKS cluster that the SQL Server 2019 CTP 3.2 big data cluster will be deployed to.\n", + "* The **Required information** cell will prompt you for password that will be used to access the cluster controller, SQL Server, and Knox.\n", + "* The values in the **Default settings** cell can be changed as appropriate.\n", + "\n", + "Please press the \"Run Cells\" button to run the notebook" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "### **Prerequisites** \n", + "Ensure the following tools are installed and added to PATH before proceeding.\n", + " \n", + "|Tools|Description|Installation|\n", + "|---|---|---|\n", + "|kubectl | Command-line tool for monitoring the underlying Kuberentes cluster | [Installation](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-binary-using-native-package-management) |\n", + "|azdata | Command-line tool for installing and managing a big data cluster |[Installation](https://docs.microsoft.com/en-us/sql/big-data-cluster/deploy-install-azdata?view=sqlallproducts-allversions) |" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": "### **Check dependencies**", + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "import pandas,sys,os,json,html,getpass,time\r\n", + "pandas_version = pandas.__version__.split('.')\r\n", + "pandas_major = int(pandas_version[0])\r\n", + "pandas_minor = int(pandas_version[1])\r\n", + "pandas_patch = int(pandas_version[2])\r\n", + "if not (pandas_major > 0 or (pandas_major == 0 and pandas_minor > 24) or (pandas_major == 0 and pandas_minor == 24 and pandas_patch >= 2)):\r\n", + " sys.exit('Please upgrade the Notebook dependency before you can proceed, you can do it by running the \"Reinstall Notebook dependencies\" command in Azure Data Studio.')\r\n", + "\r\n", + "def run_command():\r\n", + " print(\"Executing: \" + cmd)\r\n", + " !{cmd}\r\n", + " if _exit_code != 0:\r\n", + " sys.exit(f'Command execution failed with exit code: {str(_exit_code)}.\\n\\t{cmd}\\n')\r\n", + " print(f'Successfully executed: {cmd}')\r\n", + "\r\n", + "cmd = 'kubectl version --client=true'\r\n", + "run_command()\r\n", + "cmd = 'azdata --version'\r\n", + "run_command()" + ], + "metadata": {}, + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": "### **Show current context**", + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "cmd = ' kubectl config current-context'\r\n", + "run_command()" + ], + "metadata": {}, + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": "### **Required information**", + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "env_var_flag = \"AZDATA_NB_VAR_BDC_CONTROLLER_PASSWORD\" in os.environ\n", + "if env_var_flag:\n", + " mssql_password = os.environ[\"AZDATA_NB_VAR_BDC_CONTROLLER_PASSWORD\"]\n", + "else: \n", + " mssql_password = getpass.getpass(prompt = 'SQL Server 2019 big data cluster controller password')\n", + " if mssql_password == \"\":\n", + " sys.exit(f'Password is required.')\n", + " confirm_password = getpass.getpass(prompt = 'Confirm password')\n", + " if mssql_password != confirm_password:\n", + " sys.exit(f'Passwords do not match.')\n", + "print('Password accepted, you can also use the same password to access Knox and SQL Server.')" + ], + "metadata": {}, + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": "### **Default settings**", + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "if env_var_flag:\n", + " mssql_cluster_name = os.environ[\"AZDATA_NB_VAR_BDC_NAME\"]\n", + " mssql_controller_username = os.environ[\"AZDATA_NB_VAR_BDC_CONTROLLER_USERNAME\"]\n", + "else:\n", + " mssql_cluster_name = 'mssql-cluster'\n", + " mssql_controller_username = 'admin'\n", + "configuration_profile = 'aks-dev-test'\n", + "configuration_folder = 'mssql-bdc-configuration'\n", + "print(f'SQL Server big data cluster name: {mssql_cluster_name}')\n", + "print(f'SQL Server big data cluster controller user name: {mssql_controller_username}')\n", + "print(f'Deployment configuration profile: {configuration_profile}')\n", + "print(f'Deployment configuration: {configuration_folder}')" + ], + "metadata": {}, + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": "### **Create a deployment configuration file**", + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "os.environ[\"ACCEPT_EULA\"] = 'yes'\n", + "cmd = f'azdata bdc config init --source {configuration_profile} --target {configuration_folder} --force'\n", + "run_command()\n", + "cmd = f'azdata bdc config replace -c {configuration_folder}/cluster.json -j metadata.name={mssql_cluster_name}'\n", + "run_command()" + ], + "metadata": {}, + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": "### **Create SQL Server 2019 big data cluster**", + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "print (f'Creating SQL Server 2019 big data cluster: {mssql_cluster_name} using configuration {configuration_folder}')\n", + "os.environ[\"CONTROLLER_USERNAME\"] = mssql_controller_username\n", + "os.environ[\"CONTROLLER_PASSWORD\"] = mssql_password\n", + "os.environ[\"MSSQL_SA_PASSWORD\"] = mssql_password\n", + "os.environ[\"KNOX_PASSWORD\"] = mssql_password\n", + "cmd = f'azdata bdc create -c {configuration_folder}'\n", + "run_command()" + ], + "metadata": {}, + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": "### **Login to SQL Server 2019 big data cluster**", + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "cmd = f'azdata login --cluster-name {mssql_cluster_name}'\n", + "run_command()" + ], + "metadata": {}, + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": "### **Show SQL Server 2019 big data cluster endpoints**", + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "from IPython.display import *\n", + "pandas.set_option('display.max_colwidth', -1)\n", + "cmd = f'azdata bdc endpoint list'\n", + "cmdOutput = !{cmd}\n", + "endpoints = json.loads(''.join(cmdOutput))\n", + "endpointsDataFrame = pandas.DataFrame(endpoints)\n", + "endpointsDataFrame.columns = [' '.join(word[0].upper() + word[1:] for word in columnName.split()) for columnName in endpoints[0].keys()]\n", + "display(HTML(endpointsDataFrame.to_html(index=False, render_links=True)))" + ], + "metadata": {}, + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "source": [ + "### **Connect to master SQL Server instance in Azure Data Studio**\r\n", + "Click the link below to connect to the master SQL Server instance of the SQL Server 2019 big data cluster." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "sqlEndpoints = [x for x in endpoints if x['name'] == 'sql-server-master']\r\n", + "if sqlEndpoints and len(sqlEndpoints) == 1:\r\n", + " connectionParameter = '{\"serverName\":\"' + sqlEndpoints[0]['endpoint'] + '\",\"providerName\":\"MSSQL\",\"authenticationType\":\"SqlLogin\",\"userName\":\"sa\",\"password\":' + json.dumps(mssql_password) + '}'\r\n", + " display(HTML('
Click here to connect to master SQL Server instance
'))\r\n", + "else:\r\n", + " sys.exit('Could not find the master SQL Server instance endpoint')" + ], + "metadata": {}, + "outputs": [], + "execution_count": 10 + } + ] +} \ No newline at end of file diff --git a/extensions/resource-deployment/notebooks/bdc/2019/deploy-bdc-existing-cluster.ipynb b/extensions/resource-deployment/notebooks/bdc/2019/deploy-bdc-existing-cluster.ipynb deleted file mode 100644 index c5c320fa30..0000000000 --- a/extensions/resource-deployment/notebooks/bdc/2019/deploy-bdc-existing-cluster.ipynb +++ /dev/null @@ -1,142 +0,0 @@ -{ - "metadata": { - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python", - "version": "3.6.6", - "mimetype": "text/x-python", - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "pygments_lexer": "ipython3", - "nbconvert_exporter": "python", - "file_extension": ".py" - } - }, - "nbformat_minor": 2, - "nbformat": 4, - "cells": [ - { - "cell_type": "markdown", - "source": "![Microsoft](https://raw.githubusercontent.com/microsoft/azuredatastudio/master/src/sql/media/microsoft-small-logo.png)\n \n## Deploy SQL Server 2019 CTP 3.2 big data cluster on an existing Azure Kubernetes Service (AKS) cluster\n \nThis notebook walks through the process of deploying a SQL Server 2019 CTP 3.2 big data cluster on an existing AKS cluster.\n \n* Follow the instructions in the **Prerequisites** cell to install the tools if not already installed.\n* Make sure you have the target cluster set as the current context in your kubectl config file.\n The config file would typically be under C:\\Users\\(userid)\\.kube on Windows, and under ~/.kube/ for macOS and Linux for a default installation.\n In the kubectl config file, look for \"current-context\" and ensure it is set to the AKS cluster that the SQL Server 2019 CTP 3.2 big data cluster will be deployed to.\n* The **Required information** cell will prompt you for password that will be used to access the cluster controller, SQL Server, and Knox.\n* The values in the **Default settings** cell can be changed as appropriate.", - "metadata": {} - }, - { - "cell_type": "markdown", - "source": "### **Prerequisites** \nEnsure the following tools are installed and added to PATH before proceeding.\n \n|Tools|Description|Installation|\n|---|---|---|\n|kubectl | Command-line tool for monitoring the underlying Kuberentes cluster | [Installation](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-binary-using-native-package-management) |\n|azdata | Command-line tool for installing and managing a big data cluster |[Installation](https://docs.microsoft.com/en-us/sql/big-data-cluster/deploy-install-azdata?view=sqlallproducts-allversions) |", - "metadata": {} - }, - { - "cell_type": "markdown", - "source": "### **Check dependencies**", - "metadata": {} - }, - { - "cell_type": "code", - "source": "import sys\r\ndef run_command():\r\n print(\"Executing: \" + cmd)\r\n !{cmd}\r\n if _exit_code != 0:\r\n sys.exit(f'Command execution failed with exit code: {str(_exit_code)}.\\n\\t{cmd}\\n')\r\n print(f'Successfully executed: {cmd}')\r\n\r\ncmd = 'kubectl version --client=true'\r\nrun_command()\r\ncmd = 'azdata --version'\r\nrun_command()", - "metadata": {}, - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "markdown", - "source": "### **Show current context**", - "metadata": {} - }, - { - "cell_type": "code", - "source": "cmd = ' kubectl config current-context'\r\nrun_command()", - "metadata": {}, - "outputs": [], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "source": "### **Required information**", - "metadata": {} - }, - { - "cell_type": "code", - "source": "import getpass\nmssql_password = getpass.getpass(prompt = 'SQL Server 2019 big data cluster controller password')\nif mssql_password == \"\":\n sys.exit(f'Password is required')\nconfirm_password = getpass.getpass(prompt = 'Confirm password')\nif mssql_password != confirm_password:\n sys.exit(f'Passwords do not match.')\nprint('Password accepted, you can also use the same password to access Knox and SQL Server.')", - "metadata": {}, - "outputs": [], - "execution_count": 3 - }, - { - "cell_type": "markdown", - "source": "### **Default settings**", - "metadata": {} - }, - { - "cell_type": "code", - "source": "mssql_cluster_name = 'mssql-cluster'\nmssql_controller_username = 'admin'\nconfiguration_profile = 'aks-dev-test'\nconfiguration_folder = 'mssql-bdc-configuration'\nprint(f'SQL Server big data cluster name: {mssql_cluster_name}')\nprint(f'SQL Server big data cluster controller user name: {mssql_controller_username}')\nprint(f'Deployment configuration profile: {configuration_profile}')\nprint(f'Deployment configuration: {configuration_folder}')", - "metadata": {}, - "outputs": [], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "source": "### **Create a deployment configuration file**", - "metadata": {} - }, - { - "cell_type": "code", - "source": "import os\nos.environ[\"ACCEPT_EULA\"] = 'yes'\ncmd = f'azdata bdc config init --source {configuration_profile} --target {configuration_folder} --force'\nrun_command()\ncmd = f'azdata bdc config replace -c {configuration_folder}/cluster.json -j metadata.name={mssql_cluster_name}'\nrun_command()", - "metadata": {}, - "outputs": [], - "execution_count": 6 - }, - { - "cell_type": "markdown", - "source": "### **Create SQL Server 2019 big data cluster**", - "metadata": {} - }, - { - "cell_type": "code", - "source": "import os\nprint (f'Creating SQL Server 2019 big data cluster: {mssql_cluster_name} using configuration {configuration_folder}')\nos.environ[\"CONTROLLER_USERNAME\"] = mssql_controller_username\nos.environ[\"CONTROLLER_PASSWORD\"] = mssql_password\nos.environ[\"MSSQL_SA_PASSWORD\"] = mssql_password\nos.environ[\"KNOX_PASSWORD\"] = mssql_password\ncmd = f'azdata bdc create -c {configuration_folder}'\nrun_command()", - "metadata": {}, - "outputs": [], - "execution_count": 7 - }, - { - "cell_type": "markdown", - "source": "### **Login to SQL Server 2019 big data cluster**", - "metadata": {} - }, - { - "cell_type": "code", - "source": "cmd = f'azdata login --cluster-name {mssql_cluster_name}'\nrun_command()", - "metadata": {}, - "outputs": [], - "execution_count": 8 - }, - { - "cell_type": "markdown", - "source": "### **Show SQL Server 2019 big data cluster endpoints**", - "metadata": {} - }, - { - "cell_type": "code", - "source": "import json,html,pandas\nfrom IPython.display import *\npandas.set_option('display.max_colwidth', -1)\ncmd = f'azdata bdc endpoint list'\ncmdOutput = !{cmd}\nendpoints = json.loads(''.join(cmdOutput))\nendpointsDataFrame = pandas.DataFrame(endpoints)\nendpointsDataFrame.columns = [' '.join(word[0].upper() + word[1:] for word in columnName.split()) for columnName in endpoints[0].keys()]\ndisplay(HTML(endpointsDataFrame.to_html(index=False, render_links=True)))", - "metadata": {}, - "outputs": [], - "execution_count": 9 - }, - { - "cell_type": "markdown", - "source": "### **Connect to master SQL Server instance in Azure Data Studio**\r\nClick the link below to connect to the master SQL Server instance of the SQL Server 2019 big data cluster.", - "metadata": {} - }, - { - "cell_type": "code", - "source": "sqlEndpoints = [x for x in endpoints if x['name'] == 'sql-server-master']\r\nif sqlEndpoints and len(sqlEndpoints) == 1:\r\n connectionParameter = '{\"serverName\":\"' + sqlEndpoints[0]['endpoint'] + '\",\"providerName\":\"MSSQL\",\"authenticationType\":\"SqlLogin\",\"userName\":\"sa\",\"password\":' + json.dumps(mssql_password) + '}'\r\n display(HTML('
Click here to connect to master SQL Server instance
'))\r\nelse:\r\n sys.exit('Could not find the master SQL Server instance endpoint')", - "metadata": {}, - "outputs": [], - "execution_count": 10 - } - ] -} \ No newline at end of file diff --git a/extensions/resource-deployment/notebooks/docker/2017/deploy-sql2017-image.ipynb b/extensions/resource-deployment/notebooks/docker/2017/deploy-sql2017-image.ipynb index 48056c5976..5f6245674a 100644 --- a/extensions/resource-deployment/notebooks/docker/2017/deploy-sql2017-image.ipynb +++ b/extensions/resource-deployment/notebooks/docker/2017/deploy-sql2017-image.ipynb @@ -6,7 +6,7 @@ }, "language_info": { "name": "python", - "version": "3.6.6", + "version": "3.7.3", "mimetype": "text/x-python", "codemirror_mode": { "name": "ipython", @@ -22,7 +22,16 @@ "cells": [ { "cell_type": "markdown", - "source": "![Microsoft](https://raw.githubusercontent.com/microsoft/azuredatastudio/master/src/sql/media/microsoft-small-logo.png)\r\n## Run SQL Server 2017 container images with Docker\r\nThis notebook will use Docker to pull and run the SQL Server 2017 container image and connect to it in Azure Data Studio\r\n\r\n### Dependencies\r\n- Docker Engine. For more information, see [Install Docker](https://docs.docker.com/engine/installation/).", + "source": [ + "![Microsoft](https://raw.githubusercontent.com/microsoft/azuredatastudio/master/src/sql/media/microsoft-small-logo.png)\r\n", + "## Run SQL Server 2017 container images with Docker\r\n", + "This notebook will use Docker to pull and run the SQL Server 2017 container image and connect to it in Azure Data Studio\r\n", + "\r\n", + "### Dependencies\r\n", + "- Docker Engine. For more information, see [Install Docker](https://docs.docker.com/engine/installation/).\r\n", + "\r\n", + "Please press the \"Run Cells\" button to run the notebook" + ], "metadata": {} }, { @@ -32,19 +41,43 @@ }, { "cell_type": "code", - "source": "def run_command():\r\n print(\"Executing: \" + cmd)\r\n !{cmd}\r\n if _exit_code != 0:\r\n raise SystemExit(f'Shell command:\\n\\n\\t{cmd}\\n\\nreturned non-zero exit code: ' + str(_exit_code) + '.\\n')\r\n print(f'Successfully executed: {cmd}')\r\n\r\ncmd = 'docker version'\r\nrun_command()", + "source": [ + "import pandas,sys,getpass,os,json,html,time\r\n", + "pandas_version = pandas.__version__.split('.')\r\n", + "pandas_major = int(pandas_version[0])\r\n", + "pandas_minor = int(pandas_version[1])\r\n", + "pandas_patch = int(pandas_version[2])\r\n", + "if not (pandas_major > 0 or (pandas_major == 0 and pandas_minor > 24) or (pandas_major == 0 and pandas_minor == 24 and pandas_patch >= 2)):\r\n", + " sys.exit('Please upgrade the Notebook dependency before you can proceed, you can do it by running the \"Reinstall Notebook dependencies\" command in Azure Data Studio.')\r\n", + "\r\n", + "def run_command():\r\n", + " print(\"Executing: \" + cmd)\r\n", + " !{cmd}\r\n", + " if _exit_code != 0:\r\n", + " sys.exit(f'Command execution failed with exit code: {str(_exit_code)}.\\n\\t{cmd}\\n')\r\n", + " print(f'Successfully executed: {cmd}')\r\n", + "\r\n", + "cmd = 'docker version'\r\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 1 }, { "cell_type": "markdown", - "source": "### List existing containers\r\nYou can view the ports that have been used by existing containers", + "source": [ + "### List existing containers\r\n", + "You can view the ports that have been used by existing containers" + ], "metadata": {} }, { "cell_type": "code", - "source": "cmd = f'docker ps -a'\r\nrun_command()", + "source": [ + "cmd = f'docker ps -a'\r\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 2 @@ -56,7 +89,23 @@ }, { "cell_type": "code", - "source": "import getpass\r\npassword_name = 'SQL Server sa account password'\r\nsql_password = getpass.getpass(prompt = password_name)\r\npassword_confirm = getpass.getpass(prompt = f'Confirm {password_name}')\r\nif sql_password != password_confirm:\r\n raise SystemExit(f'{password_name} does not match the confirmation password')\r\nprint(f'{password_name}: ******')\r\nsql_port = input('SQL Server port, default value is 1433')\r\nif len(sql_port) == 0:\r\n sql_port = '1433'\r\nprint(f'Port: {sql_port}')", + "source": [ + "env_var_flag = \"AZDATA_NB_VAR_DOCKER_PASSWORD\" in os.environ\r\n", + "password_name = 'SQL Server sa account password'\r\n", + "if env_var_flag:\r\n", + " sql_password = os.environ[\"AZDATA_NB_VAR_DOCKER_PASSWORD\"]\r\n", + " sql_port = os.environ[\"AZDATA_NB_VAR_DOCKER_PORT\"]\r\n", + "else:\r\n", + " sql_password = getpass.getpass(prompt = password_name)\r\n", + " password_confirm = getpass.getpass(prompt = f'Confirm {password_name}')\r\n", + " if sql_password != password_confirm:\r\n", + " sys.exit(f'{password_name} does not match the confirmation password.')\r\n", + " sql_port = input('SQL Server port, default value is 1433')\r\n", + " if len(sql_port) == 0:\r\n", + " sql_port = '1433'\r\n", + "print(f'{password_name}: ******')\r\n", + "print(f'Port: {sql_port}')" + ], "metadata": {}, "outputs": [], "execution_count": 3 @@ -68,7 +117,10 @@ }, { "cell_type": "code", - "source": "cmd = f'docker pull mcr.microsoft.com/mssql/server:2017-latest'\r\nrun_command()", + "source": [ + "cmd = f'docker pull mcr.microsoft.com/mssql/server:2017-latest'\r\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 4 @@ -80,7 +132,15 @@ }, { "cell_type": "code", - "source": "import time\r\ncontainer_name = 'sql2017-' + time.strftime(\"%Y%m%d%H%M%S\", time.localtime())\r\nprint('New container name: ' + container_name)\r\ncmd = f'docker run -e ACCEPT_EULA=Y -e \"SA_PASSWORD={sql_password}\" -p {sql_port}:1433 --name {container_name} -d mcr.microsoft.com/mssql/server:2017-latest'\r\nrun_command()", + "source": [ + "if env_var_flag:\r\n", + " container_name = os.environ[\"AZDATA_NB_VAR_DOCKER_CONTAINER_NAME\"]\r\n", + "else:\r\n", + " container_name = 'sql2017-' + time.strftime(\"%Y%m%d%H%M%S\", time.localtime())\r\n", + "print('New container name: ' + container_name)\r\n", + "cmd = f'docker run -e ACCEPT_EULA=Y -e \"SA_PASSWORD={sql_password}\" -p {sql_port}:1433 --name {container_name} -d mcr.microsoft.com/mssql/server:2017-latest'\r\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 5 @@ -92,19 +152,29 @@ }, { "cell_type": "code", - "source": "cmd = f'docker ps -a'\r\nrun_command()", + "source": [ + "cmd = f'docker ps -a'\r\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 6 }, { "cell_type": "markdown", - "source": "### Connect to SQL Server in Azure Data Studio\r\nIt might take a couple minutes for SQL Server to launch", + "source": [ + "### Connect to SQL Server in Azure Data Studio\r\n", + "It might take a couple minutes for SQL Server to launch" + ], "metadata": {} }, { "cell_type": "code", - "source": "from IPython.display import *\r\ndisplay(HTML(\"

Click here to connect to SQL Server

\"))", + "source": [ + "from IPython.display import *\r\n", + "connectionParameter = '{\"serverName\":\"localhost,' + sql_port + '\",\"providerName\":\"MSSQL\",\"authenticationType\":\"SqlLogin\",\"userName\":\"sa\",\"password\":' + json.dumps(sql_password) + '}'\r\n", + "display(HTML('
Click here to connect to SQL Server
'))" + ], "metadata": {}, "outputs": [], "execution_count": 7 @@ -116,7 +186,13 @@ }, { "cell_type": "code", - "source": "stop_container_command = f'docker stop {container_name}'\r\nremove_container_command = f'docker rm {container_name}'\r\ndisplay(HTML(\"Use this link to: open the terminal window in Azure Data Studio and use the links below to paste the command to the terminal.\"))\r\ndisplay(HTML(\"Stop the container: \" + stop_container_command + \"\"))\r\ndisplay(HTML(\"Remove the container: \" + remove_container_command + \"\"))", + "source": [ + "stop_container_command = f'docker stop {container_name}'\r\n", + "remove_container_command = f'docker rm {container_name}'\r\n", + "display(HTML(\"Use this link to: open the terminal window in Azure Data Studio and use the links below to paste the command to the terminal.\"))\r\n", + "display(HTML(\"Stop the container: \" + stop_container_command + \"\"))\r\n", + "display(HTML(\"Remove the container: \" + remove_container_command + \"\"))" + ], "metadata": {}, "outputs": [], "execution_count": 8 diff --git a/extensions/resource-deployment/notebooks/docker/2019/deploy-sql2019-image.ipynb b/extensions/resource-deployment/notebooks/docker/2019/deploy-sql2019-image.ipynb index 68235a8ee9..bb419e2af7 100644 --- a/extensions/resource-deployment/notebooks/docker/2019/deploy-sql2019-image.ipynb +++ b/extensions/resource-deployment/notebooks/docker/2019/deploy-sql2019-image.ipynb @@ -6,7 +6,7 @@ }, "language_info": { "name": "python", - "version": "3.6.6", + "version": "3.7.3", "mimetype": "text/x-python", "codemirror_mode": { "name": "ipython", @@ -22,7 +22,16 @@ "cells": [ { "cell_type": "markdown", - "source": "![Microsoft](https://raw.githubusercontent.com/microsoft/azuredatastudio/master/src/sql/media/microsoft-small-logo.png)\r\n## Run SQL Server 2019 CTP 3.1 container image with Docker\r\nThis notebook will use Docker to pull and run the SQL Server 2019 CTP 3.1 container image and connect to it in Azure Data Studio\r\n\r\n### Dependencies\r\n- Docker Engine. For more information, see [Install Docker](https://docs.docker.com/engine/installation/).", + "source": [ + "![Microsoft](https://raw.githubusercontent.com/microsoft/azuredatastudio/master/src/sql/media/microsoft-small-logo.png)\r\n", + "## Run SQL Server 2019 CTP 3.2 container image with Docker\r\n", + "This notebook will use Docker to pull and run the SQL Server 2019 CTP 3.2 container image and connect to it in Azure Data Studio\r\n", + "\r\n", + "### Dependencies\r\n", + "- Docker Engine. For more information, see [Install Docker](https://docs.docker.com/engine/installation/).\r\n", + "\r\n", + "Please press the \"Run Cells\" button to run the notebook" + ], "metadata": {} }, { @@ -32,19 +41,43 @@ }, { "cell_type": "code", - "source": "def run_command():\r\n print(\"Executing: \" + cmd)\r\n !{cmd}\r\n if _exit_code != 0:\r\n raise SystemExit(f'Shell command:\\n\\n\\t{cmd}\\n\\nreturned non-zero exit code: ' + str(_exit_code) + '.\\n')\r\n print(f'Successfully executed: {cmd}')\r\n\r\ncmd = 'docker version'\r\nrun_command()", + "source": [ + "import pandas,sys,os,getpass,json,html,time\r\n", + "pandas_version = pandas.__version__.split('.')\r\n", + "pandas_major = int(pandas_version[0])\r\n", + "pandas_minor = int(pandas_version[1])\r\n", + "pandas_patch = int(pandas_version[2])\r\n", + "if not (pandas_major > 0 or (pandas_major == 0 and pandas_minor > 24) or (pandas_major == 0 and pandas_minor == 24 and pandas_patch >= 2)):\r\n", + " sys.exit('Please upgrade the Notebook dependency before you can proceed, you can do it by running the \"Reinstall Notebook dependencies\" command in Azure Data Studio.')\r\n", + "\r\n", + "def run_command():\r\n", + " print(\"Executing: \" + cmd)\r\n", + " !{cmd}\r\n", + " if _exit_code != 0:\r\n", + " sys.exit(f'Command execution failed with exit code: {str(_exit_code)}.\\n\\t{cmd}\\n')\r\n", + " print(f'Successfully executed: {cmd}')\r\n", + "\r\n", + "cmd = 'docker version'\r\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 1 }, { "cell_type": "markdown", - "source": "### List existing containers\r\nYou can view the ports that have been used by existing containers", + "source": [ + "### List existing containers\r\n", + "You can view the ports that have been used by existing containers" + ], "metadata": {} }, { "cell_type": "code", - "source": "cmd = f'docker ps -a'\r\nrun_command()", + "source": [ + "cmd = f'docker ps -a'\r\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 2 @@ -56,7 +89,23 @@ }, { "cell_type": "code", - "source": "import getpass\r\npassword_name = 'SQL Server sa account password'\r\nsql_password = getpass.getpass(prompt = password_name)\r\npassword_confirm = getpass.getpass(prompt = f'Confirm {password_name}')\r\nif sql_password != password_confirm:\r\n raise SystemExit(f'{password_name} does not match the confirmation password')\r\nprint(f'{password_name}: ******')\r\nsql_port = input('SQL Server port, default value is 1433')\r\nif len(sql_port) == 0:\r\n sql_port = '1433'\r\nprint(f'Port: {sql_port}')", + "source": [ + "env_var_flag = \"AZDATA_NB_VAR_DOCKER_PASSWORD\" in os.environ\r\n", + "password_name = 'SQL Server sa account password'\r\n", + "if env_var_flag:\r\n", + " sql_password = os.environ[\"AZDATA_NB_VAR_DOCKER_PASSWORD\"]\r\n", + " sql_port = os.environ[\"AZDATA_NB_VAR_DOCKER_PORT\"]\r\n", + "else:\r\n", + " sql_password = getpass.getpass(prompt = password_name)\r\n", + " password_confirm = getpass.getpass(prompt = f'Confirm {password_name}')\r\n", + " if sql_password != password_confirm:\r\n", + " raise SystemExit(f'{password_name} does not match the confirmation password.')\r\n", + " sql_port = input('SQL Server port, default value is 1433')\r\n", + " if len(sql_port) == 0:\r\n", + " sql_port = '1433'\r\n", + "print(f'{password_name}: ******')\r\n", + "print(f'Port: {sql_port}')" + ], "metadata": {}, "outputs": [], "execution_count": 3 @@ -68,7 +117,10 @@ }, { "cell_type": "code", - "source": "cmd = f'docker pull mcr.microsoft.com/mssql/server:2019-latest'\r\nrun_command()", + "source": [ + "cmd = f'docker pull mcr.microsoft.com/mssql/server:2019-latest'\r\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 4 @@ -80,7 +132,15 @@ }, { "cell_type": "code", - "source": "import time\r\ncontainer_name = 'sql2019-' + time.strftime(\"%Y%m%d%H%M%S\", time.localtime())\r\nprint('New container name: ' + container_name)\r\ncmd = f'docker run -e ACCEPT_EULA=Y -e \"SA_PASSWORD={sql_password}\" -p {sql_port}:1433 --name {container_name} -d mcr.microsoft.com/mssql/server:2019-latest'\r\nrun_command()", + "source": [ + "if env_var_flag:\r\n", + " container_name = os.environ[\"AZDATA_NB_VAR_DOCKER_CONTAINER_NAME\"]\r\n", + "else:\r\n", + " container_name = 'sql2019-' + time.strftime(\"%Y%m%d%H%M%S\", time.localtime())\r\n", + "print('New container name: ' + container_name)\r\n", + "cmd = f'docker run -e ACCEPT_EULA=Y -e \"SA_PASSWORD={sql_password}\" -p {sql_port}:1433 --name {container_name} -d mcr.microsoft.com/mssql/server:2019-latest'\r\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 5 @@ -92,19 +152,29 @@ }, { "cell_type": "code", - "source": "cmd = f'docker ps -a'\r\nrun_command()", + "source": [ + "cmd = f'docker ps -a'\r\n", + "run_command()" + ], "metadata": {}, "outputs": [], "execution_count": 6 }, { "cell_type": "markdown", - "source": "### Connect to SQL Server in Azure Data Studio\r\nIt might take a couple minutes for SQL Server to launch", + "source": [ + "### Connect to SQL Server in Azure Data Studio\r\n", + "It might take a couple minutes for SQL Server to launch" + ], "metadata": {} }, { "cell_type": "code", - "source": "from IPython.display import *\r\ndisplay(HTML(\"Click here to connect to SQL Server\"))", + "source": [ + "from IPython.display import *\r\n", + "connectionParameter = '{\"serverName\":\"localhost,' + sql_port + '\",\"providerName\":\"MSSQL\",\"authenticationType\":\"SqlLogin\",\"userName\":\"sa\",\"password\":' + json.dumps(sql_password) + '}'\r\n", + "display(HTML('
Click here to connect to SQL Server
'))" + ], "metadata": {}, "outputs": [], "execution_count": 7 @@ -116,10 +186,16 @@ }, { "cell_type": "code", - "source": "stop_container_command = f'docker stop {container_name}'\r\nremove_container_command = f'docker rm {container_name}'\r\ndisplay(HTML(\"Use this link to: open the terminal window in Azure Data Studio and use the links below to paste the command to the terminal.\"))\r\ndisplay(HTML(\"Stop the container: \" + stop_container_command + \"\"))\r\ndisplay(HTML(\"Remove the container: \" + remove_container_command + \"\"))", + "source": [ + "stop_container_command = f'docker stop {container_name}'\r\n", + "remove_container_command = f'docker rm {container_name}'\r\n", + "display(HTML(\"Use this link to: open the terminal window in Azure Data Studio and use the links below to paste the command to the terminal.\"))\r\n", + "display(HTML(\"Stop the container: \" + stop_container_command + \"\"))\r\n", + "display(HTML(\"Remove the container: \" + remove_container_command + \"\"))" + ], "metadata": {}, "outputs": [], "execution_count": 8 } ] -} +} \ No newline at end of file diff --git a/extensions/resource-deployment/package.json b/extensions/resource-deployment/package.json index 96144adc08..6d164a99f7 100644 --- a/extensions/resource-deployment/package.json +++ b/extensions/resource-deployment/package.json @@ -93,6 +93,47 @@ ], "providers": [ { + "dialog": { + "title": "%docker-sql-2017-title%", + "name": "docker-sql-2017-dialog", + "tabs": [ + { + "title": "", + "sections": [ + { + "title": "", + "fields": [ + { + "label": "%docker-container-name-field%", + "variableName": "AZDATA_NB_VAR_DOCKER_CONTAINER_NAME", + "type": "datetime_text", + "defaultValue": "SQL2017-", + "required": true + }, + { + "label": "%docker-sql-password-field%", + "variableName": "AZDATA_NB_VAR_DOCKER_PASSWORD", + "type": "password", + "confirmationRequired": true, + "confirmationLabel": "%docker-confirm-sql-password-field%", + "defaultValue": "", + "required": true + }, + { + "label": "%docker-sql-port-field%", + "variableName": "AZDATA_NB_VAR_DOCKER_PORT", + "type": "number", + "defaultValue": "1433", + "required": true, + "min": 1, + "max": 65535 + } + ] + } + ] + } + ] + }, "notebook": "%sql-2017-docker-notebook%", "requiredTools": [ { @@ -102,6 +143,47 @@ "when": "version=sql2017" }, { + "dialog": { + "title": "%docker-sql-2019-title%", + "name": "docker-sql-2019-dialog", + "tabs": [ + { + "title": "", + "sections": [ + { + "title": "", + "fields": [ + { + "label": "%docker-container-name-field%", + "variableName": "AZDATA_NB_VAR_DOCKER_CONTAINER_NAME", + "type": "datetime_text", + "defaultValue": "SQL2019-", + "required": true + }, + { + "label": "%docker-sql-password-field%", + "variableName": "AZDATA_NB_VAR_DOCKER_PASSWORD", + "type": "password", + "confirmationRequired": true, + "confirmationLabel": "%docker-confirm-sql-password-field%", + "defaultValue": "", + "required": true + }, + { + "label": "%docker-sql-port-field%", + "variableName": "AZDATA_NB_VAR_DOCKER_PORT", + "type": "number", + "defaultValue": "1433", + "required": true, + "min": 1, + "max": 65535 + } + ] + } + ] + } + ] + }, "notebook": "%sql-2019-docker-notebook%", "requiredTools": [ { @@ -145,14 +227,103 @@ "displayName": "%bdc-deployment-target-aks%" }, { - "name": "existingCluster", - "displayName": "%bdc-deployment-target-existing-cluster%" + "name": "existingAks", + "displayName": "%bdc-deployment-target-existing-aks%" } ] } ], "providers": [ { + "dialog": { + "title": "%bdc-new-aks-dialog-title%", + "name": "bdc-new-aks-dialog", + "tabs": [ + { + "title": "", + "sections": [ + { + "title": "%bdc-cluster-settings-section-title%", + "fields": [ + { + "label": "%bdc-cluster-name-field%", + "variableName": "AZDATA_NB_VAR_BDC_NAME", + "type": "text", + "defaultValue": "mssql-cluster", + "required": true + }, + { + "label": "%bdc-controller-username-field%", + "variableName": "AZDATA_NB_VAR_BDC_CONTROLLER_USERNAME", + "type": "text", + "defaultValue": "admin", + "required": true + }, + { + "label": "%bdc-password-field%", + "variableName": "AZDATA_NB_VAR_BDC_CONTROLLER_PASSWORD", + "type": "password", + "confirmationRequired": true, + "confirmationLabel": "%bdc-confirm-password-field%", + "defaultValue": "", + "required": true + } + ] + }, + { + "title": "%bdc-azure-settings-section-title%", + "fields": [ + { + "label": "%bdc-azure-subscription-id-field%", + "variableName": "AZDATA_NB_VAR_BDC_AZURE_SUBSCRIPTION", + "type": "text", + "defaultValue": "", + "required": false, + "placeHolder": "%bdc-azure-subscription-id-placeholder%" + }, + { + "label": "%bdc-azure-resource-group-field%", + "variableName": "AZDATA_NB_VAR_BDC_RESOURCEGROUP_NAME", + "type": "datetime_text", + "defaultValue": "mssql-", + "required": true + }, + { + "label": "%bdc-azure-region-field%", + "variableName": "AZDATA_NB_VAR_BDC_AZURE_REGION", + "type": "text", + "defaultValue": "eastus", + "required": true + }, + { + "label": "%bdc-azure-aks-name-field%", + "variableName": "AZDATA_NB_VAR_BDC_AKS_NAME", + "type": "datetime_text", + "defaultValue": "mssql-", + "required": true + }, + { + "label": "%bdc-azure-vm-size-field%", + "variableName": "AZDATA_NB_VAR_BDC_AZURE_VM_SIZE", + "type": "text", + "defaultValue": "Standard_E4s_v3", + "required": true + }, + { + "label": "%bdc-azure-vm-count-field%", + "variableName": "AZDATA_NB_VAR_BDC_VM_COUNT", + "type": "number", + "defaultValue": "5", + "min": 1, + "max": 999, + "required": true + } + ] + } + ] + } + ] + }, "notebook": "%bdc-2019-aks-notebook%", "requiredTools": [ { @@ -168,7 +339,46 @@ "when": "target=aks&&version=bdc2019" }, { - "notebook": "%bdc-2019-existing-cluster-notebook%", + "dialog": { + "title": "%bdc-existing-aks-dialog-title%", + "name": "bdc-existing-aks-dialog", + "tabs": [ + { + "title": "", + "sections": [ + { + "title": "%bdc-cluster-settings-section-title%", + "fields": [ + { + "label": "%bdc-cluster-name-field%", + "variableName": "AZDATA_NB_VAR_BDC_NAME", + "type": "text", + "defaultValue": "mssql-cluster", + "required": true + }, + { + "label": "%bdc-controller-username-field%", + "variableName": "AZDATA_NB_VAR_BDC_CONTROLLER_USERNAME", + "type": "text", + "defaultValue": "admin", + "required": true + }, + { + "label": "%bdc-password-field%", + "variableName": "AZDATA_NB_VAR_BDC_CONTROLLER_PASSWORD", + "type": "password", + "confirmationRequired": true, + "confirmationLabel": "%bdc-confirm-password-field%", + "defaultValue": "", + "required": true + } + ] + } + ] + } + ] + }, + "notebook": "%bdc-2019-existing-aks-notebook%", "requiredTools": [ { "name": "kubectl" @@ -177,7 +387,7 @@ "name": "azdata" } ], - "when": "target=existingCluster&&version=bdc2019" + "when": "target=existingAks&&version=bdc2019" } ] } @@ -189,4 +399,4 @@ "typemoq": "^2.1.0", "vscode": "^1.1.26" } -} \ No newline at end of file +} diff --git a/extensions/resource-deployment/package.nls.json b/extensions/resource-deployment/package.nls.json index 71f4d28143..6760e85813 100644 --- a/extensions/resource-deployment/package.nls.json +++ b/extensions/resource-deployment/package.nls.json @@ -17,7 +17,28 @@ "bdc-2019-display-name": "SQL Server 2019 CTP 3.2 big data cluster", "bdc-deployment-target": "Deployment target", "bdc-deployment-target-aks": "New Azure Kubernetes Service Cluster", - "bdc-deployment-target-existing-cluster": "Existing Azure Kubernetes Service Cluster", + "bdc-deployment-target-existing-aks": "Existing Azure Kubernetes Service Cluster", "bdc-2019-aks-notebook": "./notebooks/bdc/2019/deploy-bdc-aks.ipynb", - "bdc-2019-existing-cluster-notebook": "./notebooks/bdc/2019/deploy-bdc-existing-cluster.ipynb" -} \ No newline at end of file + "bdc-2019-existing-aks-notebook": "./notebooks/bdc/2019/deploy-bdc-existing-aks.ipynb", + "docker-sql-2017-title": "Deploy SQL Server 2017 container images with Docker", + "docker-sql-2019-title": "Deploy SQL Server 2019 container images with Docker", + "docker-container-name-field": "Container name", + "docker-sql-password-field": "SQL Server password", + "docker-confirm-sql-password-field": "Confirm password", + "docker-sql-port-field": "Port", + "bdc-new-aks-dialog-title": "Deploy SQL Server big data cluster on new AKS cluster", + "bdc-existing-aks-dialog-title": "Deploy SQL Server big data cluster on existing AKS cluster", + "bdc-cluster-settings-section-title": "SQL Server big data cluster settings", + "bdc-cluster-name-field": "Cluster name", + "bdc-controller-username-field": "Controller username", + "bdc-password-field": "Password", + "bdc-confirm-password-field": "Confirm password", + "bdc-azure-settings-section-title": "Azure settings", + "bdc-azure-subscription-id-field": "Subscription id", + "bdc-azure-subscription-id-placeholder": "Use my default Azure subscription", + "bdc-azure-resource-group-field": "Resource group name", + "bdc-azure-region-field": "Region", + "bdc-azure-aks-name-field": "AKS cluster name", + "bdc-azure-vm-size-field": "VM size", + "bdc-azure-vm-count-field": "VM count" +} diff --git a/extensions/resource-deployment/src/interfaces.ts b/extensions/resource-deployment/src/interfaces.ts index 22291dc691..a8e24ef08b 100644 --- a/extensions/resource-deployment/src/interfaces.ts +++ b/extensions/resource-deployment/src/interfaces.ts @@ -27,11 +27,51 @@ export interface ResourceTypeOptionValue { } export interface DeploymentProvider { + title: string; + dialog: DialogInfo; notebook: string | NotebookInfo; requiredTools: ToolRequirementInfo[]; when: string; } +export interface DialogInfo { + title: string; + name: string; + tabs: DialogTabInfo[]; +} + +export interface DialogTabInfo { + title: string; + sections: DialogSectionInfo[]; +} + +export interface DialogSectionInfo { + title: string; + fields: DialogFieldInfo[]; +} + +export interface DialogFieldInfo { + label: string; + variableName: string; + type: FieldType; + defaultValue: string; + confirmationRequired: boolean; + confirmationLabel: string; + min?: number; + max?: number; + required: boolean; + options: string[]; + placeHolder: string; +} + +export enum FieldType { + Text = 'text', + Number = 'number', + DateTimeText = 'datetime_text', + Password = 'password', + Options = 'options' +} + export interface NotebookInfo { win32: string; darwin: string; @@ -55,4 +95,4 @@ export interface ITool { readonly displayName: string; readonly description: string; readonly type: ToolType; -} \ No newline at end of file +} diff --git a/extensions/resource-deployment/src/main.ts b/extensions/resource-deployment/src/main.ts index c6af2774aa..70a5a09dc0 100644 --- a/extensions/resource-deployment/src/main.ts +++ b/extensions/resource-deployment/src/main.ts @@ -5,7 +5,7 @@ 'use strict'; import vscode = require('vscode'); -import { ResourceDeploymentDialog } from './ui/resourceDeploymentDialog'; +import { ResourceTypePickerDialog } from './ui/resourceDeploymentDialog'; import { ToolsService } from './services/toolsService'; import { NotebookService } from './services/notebookService'; import { ResourceTypeService } from './services/resourceTypeService'; @@ -33,7 +33,7 @@ export function activate(context: vscode.ExtensionContext) { if (filtered.length !== 1) { vscode.window.showErrorMessage(localize('resourceDeployment.UnknownResourceType', 'The resource type: {0} is not defined', resourceTypeName)); } else { - const dialog = new ResourceDeploymentDialog(context, notebookService, toolsService, resourceTypeService, filtered[0]); + const dialog = new ResourceTypePickerDialog(context, notebookService, toolsService, resourceTypeService, filtered[0]); dialog.open(); } }; @@ -52,4 +52,4 @@ export function activate(context: vscode.ExtensionContext) { // this method is called when your extension is deactivated export function deactivate(): void { -} \ No newline at end of file +} diff --git a/extensions/resource-deployment/src/services/notebookService.ts b/extensions/resource-deployment/src/services/notebookService.ts index 332842fb00..1c8af8c514 100644 --- a/extensions/resource-deployment/src/services/notebookService.ts +++ b/extensions/resource-deployment/src/services/notebookService.ts @@ -84,4 +84,4 @@ export class NotebookService implements INotebookService { }); }); } -} \ No newline at end of file +} diff --git a/extensions/resource-deployment/src/ui/deploymentDialog.ts b/extensions/resource-deployment/src/ui/deploymentDialog.ts new file mode 100644 index 0000000000..32f0d83167 --- /dev/null +++ b/extensions/resource-deployment/src/ui/deploymentDialog.ts @@ -0,0 +1,135 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as azdata from 'azdata'; +import * as nls from 'vscode-nls'; +import * as vscode from 'vscode'; +import { DialogBase } from './dialogBase'; +import { INotebookService } from '../services/notebookService'; +import { DeploymentProvider, DialogFieldInfo, FieldType } from '../interfaces'; + +const localize = nls.loadMessageBundle(); + +export class DeploymentDialog extends DialogBase { + + private variables: { [s: string]: string | undefined; } = {}; + + constructor(context: vscode.ExtensionContext, + private notebookService: INotebookService, + private deploymentProvider: DeploymentProvider) { + super(context, deploymentProvider.dialog.title, deploymentProvider.dialog.name, false); + this._dialogObject.okButton.label = localize('deploymentDialog.OKButtonText', 'Open Notebook'); + this._dialogObject.okButton.onClick(() => this.onComplete()); + } + + protected initializeDialog() { + const tabs: azdata.window.DialogTab[] = []; + this.deploymentProvider.dialog.tabs.forEach(tabInfo => { + const tab = azdata.window.createTab(tabInfo.title); + tab.registerContent((view: azdata.ModelView) => { + const sections: azdata.FormComponentGroup[] = []; + tabInfo.sections.forEach(sectionInfo => { + const fields: azdata.FormComponent[] = []; + sectionInfo.fields.forEach(fieldInfo => { + this.addField(view, fields, fieldInfo); + }); + sections.push({ title: sectionInfo.title, components: fields }); + }); + const formBuilder = view.modelBuilder.formContainer().withFormItems( + sections, + { + horizontal: false + } + ); + + const form = formBuilder.withLayout({ width: '100%' }).component(); + + return view.initializeModel(form); + }); + tabs.push(tab); + }); + this._dialogObject.content = tabs; + } + + private addField(view: azdata.ModelView, fields: azdata.FormComponent[], fieldInfo: DialogFieldInfo): void { + switch (fieldInfo.type) { + case FieldType.Options: + this.addOptionsTypeField(view, fields, fieldInfo); + break; + case FieldType.DateTimeText: + case FieldType.Number: + case FieldType.Password: + case FieldType.Text: + this.addInputTypeField(view, fields, fieldInfo); + break; + } + } + + private addOptionsTypeField(view: azdata.ModelView, fields: azdata.FormComponent[], fieldInfo: DialogFieldInfo): void { + const component = view.modelBuilder.dropDown().withProperties({ values: fieldInfo.options, value: fieldInfo.defaultValue }).component(); + this.variables[fieldInfo.variableName] = fieldInfo.defaultValue; + this._toDispose.push(component.onValueChanged(() => { this.variables[fieldInfo.variableName] = component.value; })); + fields.push({ title: fieldInfo.label, component: component }); + } + + private addInputTypeField(view: azdata.ModelView, fields: azdata.FormComponent[], fieldInfo: DialogFieldInfo): void { + let inputType: azdata.InputBoxInputType = 'text'; + let defaultValue: string | undefined = fieldInfo.defaultValue; + + switch (fieldInfo.type) { + case FieldType.Number: + inputType = 'number'; + break; + case FieldType.Password: + inputType = 'password'; + break; + case FieldType.DateTimeText: + defaultValue = fieldInfo.defaultValue + new Date().toISOString().slice(0, 19).replace(/[^0-9]/g, ''); + break; + } + const component = view.modelBuilder.inputBox().withProperties({ + value: defaultValue, ariaLabel: fieldInfo.label, inputType: inputType, min: fieldInfo.min, max: fieldInfo.max, required: fieldInfo.required, placeHolder: fieldInfo.placeHolder + }).component(); + this.variables[fieldInfo.variableName] = defaultValue; + this._toDispose.push(component.onTextChanged(() => { this.variables[fieldInfo.variableName] = component.value; })); + fields.push({ title: fieldInfo.label, component: component }); + + if (fieldInfo.type === FieldType.Password && fieldInfo.confirmationRequired) { + const confirmPasswordComponent = view.modelBuilder.inputBox().withProperties({ ariaLabel: fieldInfo.confirmationLabel, inputType: inputType, required: true }).component(); + fields.push({ title: fieldInfo.confirmationLabel, component: confirmPasswordComponent }); + + this._dialogObject.registerCloseValidator((): boolean => { + const passwordMatches = component.value === confirmPasswordComponent.value; + if (!passwordMatches) { + this._dialogObject.message = { level: azdata.window.MessageLevel.Error, text: localize('passwordNotMatch', "{0} doesn't match the confirmation password", fieldInfo.label) }; + } + return passwordMatches; + }); + + const checkPassword = (): void => { + const passwordMatches = component.value === confirmPasswordComponent.value; + if (passwordMatches) { + this._dialogObject.message = { text: '' }; + } + }; + + this._toDispose.push(component.onTextChanged(() => { + checkPassword(); + })); + this._toDispose.push(confirmPasswordComponent.onTextChanged(() => { + checkPassword(); + })); + } + } + + private onComplete(): void { + Object.keys(this.variables).forEach(key => { + process.env[key] = this.variables[key]; + }); + this.notebookService.launchNotebook(this.deploymentProvider.notebook); + this.dispose(); + } +} diff --git a/extensions/resource-deployment/src/ui/dialogBase.ts b/extensions/resource-deployment/src/ui/dialogBase.ts new file mode 100644 index 0000000000..ad10a6f790 --- /dev/null +++ b/extensions/resource-deployment/src/ui/dialogBase.ts @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as azdata from 'azdata'; +import * as vscode from 'vscode'; + +export abstract class DialogBase { + protected _toDispose: vscode.Disposable[] = []; + protected _dialogObject: azdata.window.Dialog; + + constructor(protected extensionContext: vscode.ExtensionContext, dialogTitle: string, dialogName: string, isWide: boolean = false) { + this._dialogObject = azdata.window.createModelViewDialog(dialogTitle, dialogName, isWide); + this._dialogObject.cancelButton.onClick(() => this.onCancel()); + } + + protected abstract initializeDialog(): void; + + public open(): void { + this.initializeDialog(); + azdata.window.openDialog(this._dialogObject); + } + + protected onCancel(): void { + this.dispose(); + } + + protected dispose(): void { + this._toDispose.forEach(disposable => disposable.dispose()); + } +} diff --git a/extensions/resource-deployment/src/ui/resourceDeploymentDialog.ts b/extensions/resource-deployment/src/ui/resourceDeploymentDialog.ts index d8f6745f0d..575fef2472 100644 --- a/extensions/resource-deployment/src/ui/resourceDeploymentDialog.ts +++ b/extensions/resource-deployment/src/ui/resourceDeploymentDialog.ts @@ -11,13 +11,13 @@ import * as vscode from 'vscode'; import { ResourceType, DeploymentProvider } from '../interfaces'; import { IToolsService } from '../services/toolsService'; import { INotebookService } from '../services/notebookService'; +import { DialogBase } from './dialogBase'; +import { DeploymentDialog } from './deploymentDialog'; const localize = nls.loadMessageBundle(); -export class ResourceDeploymentDialog { +export class ResourceTypePickerDialog extends DialogBase { private _selectedResourceType: ResourceType; - private _toDispose: vscode.Disposable[] = []; - private _dialogObject: azdata.window.Dialog; private _resourceTypeCards: azdata.CardComponent[] = []; private _view!: azdata.ModelView; private _resourceDescriptionLabel!: azdata.TextComponent; @@ -26,19 +26,18 @@ export class ResourceDeploymentDialog { private _cardResourceTypeMap: Map = new Map(); private _optionDropDownMap: Map = new Map(); - constructor(private context: vscode.ExtensionContext, + constructor(context: vscode.ExtensionContext, private notebookService: INotebookService, private toolsService: IToolsService, private resourceTypeService: IResourceTypeService, resourceType: ResourceType) { + super(context, localize('resourceTypePickerDialog.title', "Select the deployment options"), 'ResourceTypePickerDialog', true); this._selectedResourceType = resourceType; - this._dialogObject = azdata.window.createModelViewDialog(localize('deploymentDialog.title', 'Select the deployment options'), 'resourceDeploymentDialog', true); - this._dialogObject.cancelButton.onClick(() => this.onCancel()); - this._dialogObject.okButton.label = localize('deploymentDialog.OKButtonText', 'Open Notebook'); + this._dialogObject.okButton.label = localize('deploymentDialog.OKButtonText', 'Select'); this._dialogObject.okButton.onClick(() => this.onComplete()); } - private initializeDialog() { + initializeDialog() { let tab = azdata.window.createTab(''); tab.registerContent((view: azdata.ModelView) => { const tableWidth = 1126; @@ -98,17 +97,12 @@ export class ResourceDeploymentDialog { this._dialogObject.content = [tab]; } - public open(): void { - this.initializeDialog(); - azdata.window.openDialog(this._dialogObject); - } - private addCard(resourceType: ResourceType): void { const card = this._view.modelBuilder.card().withProperties({ cardType: azdata.CardType.VerticalButton, iconPath: { - dark: this.context.asAbsolutePath(resourceType.icon.dark), - light: this.context.asAbsolutePath(resourceType.icon.light) + dark: this.extensionContext.asAbsolutePath(resourceType.icon.dark), + light: this.extensionContext.asAbsolutePath(resourceType.icon.light) }, label: resourceType.displayName, selected: (this._selectedResourceType && this._selectedResourceType.name === resourceType.name) @@ -180,17 +174,14 @@ export class ResourceDeploymentDialog { return this._selectedResourceType.getProvider(options)!; } - private onCancel(): void { - this.dispose(); - } - private onComplete(): void { const provider = this.getCurrentProvider(); - this.notebookService.launchNotebook(provider.notebook); + if (provider.dialog) { + const dialog = new DeploymentDialog(this.extensionContext, this.notebookService, provider); + dialog.open(); + } else { + this.notebookService.launchNotebook(provider.notebook); + } this.dispose(); } - - private dispose(): void { - this._toDispose.forEach(disposable => disposable.dispose()); - } }