Import Databricks Workbooks

Octopus.Script exported 2021-10-05 by Zogamorph belongs to ‘Databricks’ category.

Import Databricks workbooks (current supported files .ipynb and .scala) to a databricks instance

Parameters

When steps based on the template are included in a project’s deployment process, the parameters below can be set.

DataBricks WorkBook Package

DeployDataBricksWorkBookPackage =

The Databricks workbook package

Databricks Instance Uri

DataBricksInstanceUri =

The Databricks Instance URL

Databricks Access Token

DataBricksAccessToken =

The access token to authenticate against the Databricks instance

Databricks Workbook Import Folder

DatabricksImportFolder = /

Databricks Workbook import folder location

Script body

Steps based on this template will execute the following PowerShell script.

$ErrorActionPreference = "Stop" #region fucntions
function Set-DatabricksWorkBook
{
    [CmdletBinding()]
    param (
        [Parameter()]
        [String]
        $AccessToken, 
        [Parameter()]
        [String]
        $DataBricksInstanceUri,
        [Parameter()]
        [String]
        $WorkbooksUploadPath,
        [Parameter()]
        [String]
        $DatabrickImportFolder
    )

    $headers = @{
        'Authorization' = ("Bearer {0}" -f $AccessToken )
    }
    $APIVersion = '/api/2.0'
    $APICommand = '/workspace/import'
    $Uri = "https://$DataBricksInstanceUri$APIVersion$APICommand"
        
    Get-ChildItem -Path $WorkbooksUploadPath -Recurse -File | ForEach-Object{ $currentWorkBook = $_
        Write-Host ("Importing Workbook:{0}" -f $currentWorkBook.FullName)
 		$workbookContent =  [Convert]::ToBase64String((Get-Content -path $currentWorkBook.FullName -Encoding byte))
    
        if($DatabrickImportFolder.EndsWith("/"))
    	{
    		$workbookPath   = "{0}{1}" -f $DatabrickImportFolder , $currentWorkBook.BaseName
    	}
    	else 
    	{
        	$workbookPath   = "{0}/{1}" -f $DatabrickImportFolder , $currentWorkBook.BaseName
    	}
        
        switch ($currentWorkBook.Extension.ToLower()) 
        {
            '.ipynb' { 
                $workbookLanguage = "PYTHON" 
                $workbookFormat   = "JUPYTER"
                break
            }
            '.scala' {
                $workbookLanguage = "SCALA"
                $workbookFormat   = "SOURCE"
                break
        }
        Default 
            {
                $workbookLanguage = "SQL"
                $workbookFormat   = "SOURCE"
            }
        }
        $requestBody = ConvertTo-Json -InputObject @{ 
            content = $workbookContent
            path = $workbookPath
            language = $workbookLanguage
            format = $workbookFormat
            overwrite = $true
            }
        
        $apiResponse = Invoke-RestMethod -Method Post  -Uri  $Uri -Headers $headers -Body $requestBody
        return $apiResponse
    }
}


function Set-DatabricksWorkspaceFolder
{
    [CmdletBinding()]
    param (
        [Parameter()]
        [String]
        $AccessToken, 
        [Parameter()]
        [String]
        $DataBricksInstanceUri,
        [Parameter()]
        [String]
        $DatabrickFolder
    )

    $headers = @{
        'Authorization' = ("Bearer {0}" -f $AccessToken )
    }
    $APIVersion = '/api/2.0'
    $APIListCommand = '/workspace/list'
    $APIMkdirsCommand = '/workspace/mkdirs'
    $ListUri = "https://$DataBricksInstanceUri$APIVersion$APIListCommand"
    $MkdirsUri = "https://$DataBricksInstanceUri$APIVersion$APIMkdirsCommand"

    $pathRoute = $DatabrickFolder.Substring(1) -split '/'
    $basePath = "/"
    foreach($path in $pathRoute)
    {
        $requestBody = @{ 
            path = $basePath
        }
        $apiResponse = Invoke-RestMethod -Uri $ListUri -Headers $headers -Body $requestBody -ContentType application/json  
        $workSpaceFolder = $apiResponse.objects | Where-Object {$_.object_type -eq "DIRECTORY" -and $_.path -eq ( "{0}{1}" -f $basePath , $path) } 
        if($null -eq $workSpaceFolder)
        {
            $requestBody = ConvertTo-Json -InputObject  @{ 
                path = ( "{0}{1}" -f $basePath , $path)
            } 
            Invoke-RestMethod -Method Post -Uri $MkdirsUri -Headers $headers -Body $requestBody
        }
        $basePath = "{0}/{1}/" -f $basePath , $path
        if($basePath.StartsWith("//"))
        {
            $basePath = $basePath.Substring(1)
        }
    }
}

#endregion fucntions


$DatabrickWorkBookImportFolder = $OctopusParameters["Octopus.Action.Package[DeployDataBricksWorkBookPackage].ExtractedPath"]

Write-Host "Checking WorkSpace Folders"
Set-DatabricksWorkspaceFolder  -AccessToken $DataBricksAccessToken -DataBricksInstanceUri $DataBricksInstanceUri -DatabrickFolder $DatabricksImportFolder
Write-Host "Importing Databricks Workbooks"
Set-DatabricksWorkBook -AccessToken $DataBricksAccessToken -DataBricksInstanceUri $DataBricksInstanceUri -WorkbooksUploadPath $DatabrickWorkBookImportFolder -DatabrickImportFolder $DatabricksImportFolder

Provided under the Apache License version 2.0.

Report an issue

To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.

{
  "Id": "0bbe289c-3ea9-47f8-970c-caa946878f49",
  "Name": "Import Databricks Workbooks",
  "Description": "Import Databricks workbooks (current supported files `.ipynb` and `.scala`) to a databricks instance",
  "Version": 1,
  "ExportedAt": "2021-10-05T09:38:27.445Z",
  "ActionType": "Octopus.Script",
  "Author": "Zogamorph",
  "Packages": [
    {
      "Id": "7885715a-c3e8-492a-ba61-23c34d2e9447",
      "Name": "DeployDataBricksWorkBookPackage",
      "PackageId": null,
      "FeedId": null,
      "AcquisitionLocation": "Server",
      "Properties": {
        "Extract": "True",
        "SelectionMode": "deferred",
        "PackageParameterName": "DeployDataBricksWorkBookPackage"
      }
    }
  ],
  "Parameters": [
    {
      "Id": "b8cd5d73-29d9-4ba2-bdfa-86cc1316a16f",
      "Name": "DeployDataBricksWorkBookPackage",
      "Label": "DataBricks WorkBook Package",
      "HelpText": "The Databricks workbook package",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Package"
      }
    },
    {
      "Id": "f81b9ccb-beea-4d8f-a049-ee9ea6da643e",
      "Name": "DataBricksInstanceUri",
      "Label": "Databricks Instance Uri",
      "HelpText": "The Databricks Instance URL",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "6c1aed25-f9a6-4c1f-b8e9-d50cc8669f2d",
      "Name": "DataBricksAccessToken",
      "Label": "Databricks Access Token",
      "HelpText": "The access token to authenticate against the Databricks instance",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Sensitive"
      }
    },
    {
      "Id": "c95af088-180b-419e-8c44-ce3fb4d96f57",
      "Name": "DatabricksImportFolder",
      "Label": "Databricks Workbook Import Folder",
      "HelpText": "Databricks Workbook import folder location",
      "DefaultValue": "/",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptBody": "$ErrorActionPreference = \"Stop\" #region fucntions\nfunction Set-DatabricksWorkBook\n{\n    [CmdletBinding()]\n    param (\n        [Parameter()]\n        [String]\n        $AccessToken, \n        [Parameter()]\n        [String]\n        $DataBricksInstanceUri,\n        [Parameter()]\n        [String]\n        $WorkbooksUploadPath,\n        [Parameter()]\n        [String]\n        $DatabrickImportFolder\n    )\n\n    $headers = @{\n        'Authorization' = (\"Bearer {0}\" -f $AccessToken )\n    }\n    $APIVersion = '/api/2.0'\n    $APICommand = '/workspace/import'\n    $Uri = \"https://$DataBricksInstanceUri$APIVersion$APICommand\"\n        \n    Get-ChildItem -Path $WorkbooksUploadPath -Recurse -File | ForEach-Object{ $currentWorkBook = $_\n        Write-Host (\"Importing Workbook:{0}\" -f $currentWorkBook.FullName)\n \t\t$workbookContent =  [Convert]::ToBase64String((Get-Content -path $currentWorkBook.FullName -Encoding byte))\n    \n        if($DatabrickImportFolder.EndsWith(\"/\"))\n    \t{\n    \t\t$workbookPath   = \"{0}{1}\" -f $DatabrickImportFolder , $currentWorkBook.BaseName\n    \t}\n    \telse \n    \t{\n        \t$workbookPath   = \"{0}/{1}\" -f $DatabrickImportFolder , $currentWorkBook.BaseName\n    \t}\n        \n        switch ($currentWorkBook.Extension.ToLower()) \n        {\n            '.ipynb' { \n                $workbookLanguage = \"PYTHON\" \n                $workbookFormat   = \"JUPYTER\"\n                break\n            }\n            '.scala' {\n                $workbookLanguage = \"SCALA\"\n                $workbookFormat   = \"SOURCE\"\n                break\n        }\n        Default \n            {\n                $workbookLanguage = \"SQL\"\n                $workbookFormat   = \"SOURCE\"\n            }\n        }\n        $requestBody = ConvertTo-Json -InputObject @{ \n            content = $workbookContent\n            path = $workbookPath\n            language = $workbookLanguage\n            format = $workbookFormat\n            overwrite = $true\n            }\n        \n        $apiResponse = Invoke-RestMethod -Method Post  -Uri  $Uri -Headers $headers -Body $requestBody\n        return $apiResponse\n    }\n}\n\n\nfunction Set-DatabricksWorkspaceFolder\n{\n    [CmdletBinding()]\n    param (\n        [Parameter()]\n        [String]\n        $AccessToken, \n        [Parameter()]\n        [String]\n        $DataBricksInstanceUri,\n        [Parameter()]\n        [String]\n        $DatabrickFolder\n    )\n\n    $headers = @{\n        'Authorization' = (\"Bearer {0}\" -f $AccessToken )\n    }\n    $APIVersion = '/api/2.0'\n    $APIListCommand = '/workspace/list'\n    $APIMkdirsCommand = '/workspace/mkdirs'\n    $ListUri = \"https://$DataBricksInstanceUri$APIVersion$APIListCommand\"\n    $MkdirsUri = \"https://$DataBricksInstanceUri$APIVersion$APIMkdirsCommand\"\n\n    $pathRoute = $DatabrickFolder.Substring(1) -split '/'\n    $basePath = \"/\"\n    foreach($path in $pathRoute)\n    {\n        $requestBody = @{ \n            path = $basePath\n        }\n        $apiResponse = Invoke-RestMethod -Uri $ListUri -Headers $headers -Body $requestBody -ContentType application/json  \n        $workSpaceFolder = $apiResponse.objects | Where-Object {$_.object_type -eq \"DIRECTORY\" -and $_.path -eq ( \"{0}{1}\" -f $basePath , $path) } \n        if($null -eq $workSpaceFolder)\n        {\n            $requestBody = ConvertTo-Json -InputObject  @{ \n                path = ( \"{0}{1}\" -f $basePath , $path)\n            } \n            Invoke-RestMethod -Method Post -Uri $MkdirsUri -Headers $headers -Body $requestBody\n        }\n        $basePath = \"{0}/{1}/\" -f $basePath , $path\n        if($basePath.StartsWith(\"//\"))\n        {\n            $basePath = $basePath.Substring(1)\n        }\n    }\n}\n\n#endregion fucntions\n\n\n$DatabrickWorkBookImportFolder = $OctopusParameters[\"Octopus.Action.Package[DeployDataBricksWorkBookPackage].ExtractedPath\"]\n\nWrite-Host \"Checking WorkSpace Folders\"\nSet-DatabricksWorkspaceFolder  -AccessToken $DataBricksAccessToken -DataBricksInstanceUri $DataBricksInstanceUri -DatabrickFolder $DatabricksImportFolder\nWrite-Host \"Importing Databricks Workbooks\"\nSet-DatabricksWorkBook -AccessToken $DataBricksAccessToken -DataBricksInstanceUri $DataBricksInstanceUri -WorkbooksUploadPath $DatabrickWorkBookImportFolder -DatabrickImportFolder $DatabricksImportFolder\n"
  },
  "Category": "Databricks",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/import-databricks-workbooks.json",
  "Website": "/step-templates/0bbe289c-3ea9-47f8-970c-caa946878f49",
  "Logo": "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",
  "$Meta": {
    "Type": "ActionTemplate"
  }
}

History

Page updated on Tuesday, October 5, 2021