DD.QA.Tools.psm1

<#
.Description
Ensuring the Chocolatey package manager is installed. If Chocolatey is not installed, will download and install it;
otherwise skip the installation.
#>

Function Install-Chocolatey{
    $chocolateyBin = [Environment]::GetEnvironmentVariable("ChocolateyInstall", "Machine") + "\bin"
    $chocolateyExe = "$chocolateyBin\cinst.exe"
    $chocInstalled = Test-Path $chocolateyExe

    if (-not $chocInstalled) {
      Write-Output "Chocolatey not found, installing..."

      $installPs1 = ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))
      Invoke-Expression $installPs1

      Write-Output "Chocolatey installation complete."
    } else {
      Write-Output "Chocolatey was found at $chocolateyBin and won't be reinstalled."
    }
    # TODO: Set environment variable after the installation.
}

<#
.Description
Converts from secure string to string.
#>

Function ConvertTo-String{
    param(
        [parameter(
            Mandatory         = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        $SecureString
    )
    if ($SecureString -ne $null)
    {
        [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString))
    }
}

<#
.Description
Configure the portal user credentials. If The user has not been created, creats the portal user;
If there is already an exsiting user identified by the user key, then update this user.
#>

Function Set-PortalUser{
    param (
        [Parameter(Mandatory=$true)]
        $libPath,
        $userKey = 'DD Admin',
        $email,
        [Parameter(Mandatory=$true)]
        $upn,
        $userName,
        [Parameter(Mandatory=$true)]
        $password
    )
    
    $packageName = 'dd.qa.ms.powershell'

    if([string]::IsNullOrEmpty($libPath)){
        throw [System.ArgumentException]"The path to the '$packageName' needs to be specified."
    }

    $packageDll = Get-ChildItem -Path $libPath -Recurse  (-join ($packageName, '.dll'))

    if($packageDll)
    {
        Write-Information ("Importing binary powershell module '{0}'" -f $packageDll.Name)
        $packageDll.FullName | Import-Module
        
        # Call the New-PortalUser cmlet to create a new portal user
        if($password -and $upn)
        {
            Write-Host "Creating user record with user key '$userKey'"
            New-PortalUser -UserKey $userKey -Upn $upn -Password $password -Email $email -UserName $userName
        }else
        {
            Write-Warning 'User password and upn are mandatory for ceating a new portal user.'
        }
    }
    else
    {    
        Write-Warning ("'$packageName' has not been installed")
        Write-Host ("Use the Install-NugetPackage command to install '$packageName'")
    }
}

Function Import-PackageModule{
    param (
        [Parameter(HelpMessage="The package name that contains powershell module to import.")]
        $packageName,
        $moduleName = $packageName
    )

    if(!$packageName)
    {
        Write-Warning "Package name cannot be null or empty"
        return
    }

    $package = Get-Package -Name $packageName -ProviderName NuGet -ErrorAction SilentlyContinue

    if ($package -ne $null)
    {
        $packageFolder = $package.Source | Split-Path -Parent -Resolve

        $moduleDll = Get-ChildItem -Path $packageFolder -Recurse  (-join ($moduleName, '.dll'))

        if($moduleDll)
        {
            Write-Information ("Importing binary powershell module '{0}'" -f $moduleDll.Name)
            Import-Module $moduleDll.FullName
        }
    }
}

<#
.Description
Install nuget package using the Package Management module.
#>

Function Install-NugetPackage
{
    param (
        [Parameter(HelpMessage = "The nuget package name or id.")]
        $name,
        [Parameter(HelpMessage = "The nuget package source name.")]
        $source = 'QA.Package',
        [Parameter(HelpMessage = "Indicates whether to redefine the package source.")]
        [switch] $resetPackageSource,
        [Parameter(HelpMessage = "The nuget package feed location.")]
        $sourceLocation,
        [Parameter(HelpMessage = "The user name to access the nuget package feed.")]
        $userName,
        [Parameter(HelpMessage = "The user password to access the nuget package feed.")]
        $password,
        [Parameter(HelpMessage = "Indicates whether to uninstall any existing packages.")]
        [switch] $cleanup = $true
    )

    if($cleanup) 
    {
        Get-Package -Name $name -AllVersions -ErrorAction SilentlyContinue | Uninstall-Package -Force -ErrorAction SilentlyContinue
    }
    if($password -and $userName)
    {
        $securedPassword = ConvertTo-SecureString $password -AsPlainText -Force
        $credential = New-Object System.Management.Automation.PSCredential($userName, $securedPassword)
        Write-Host 'Creating PSCredential ...'
    }
    else{
        $credential = Get-Credential -Message "Credential to look up packages"
    }

    if($resetPackageSource)
    {
        Get-PackageSource -Name $source -ErrorAction Ignore | Unregister-PackageSource -Force
    }

    # Register package source if not found
    if((Get-PackageSource -Name $source -ErrorAction Ignore) -eq $null)
    {
        Register-PackageSource -Name $source -Location $sourceLocation -ProviderName NuGet -Trusted -Credential $credential
    }

    Find-Package -name $name -Source $source -Credential $credential| Install-Package -credential $credential -Force | Out-Null
}

<#
.Description
Configure the app settings section in any web.config or app.config file. Create the key-value pair if does not exist,
Otherwise update existing value.
#>

Function Set-AppSettings()
{
    param(
        [Parameter(HelpMessage="The configuration file content as an xml document object.", Mandatory=$True,Position=1)]
        [xml] $document, 
        [Parameter(HelpMessage="The app settings key name")]
        [string] $key,
        [Parameter(HelpMessage="The app settings value")]
        [string] $value
    )

    $appSettings = $document.appSettings
    
    if ($appSettings -eq $null)
    {
        Write-Warning "The document does not have App settings section."
        return
    }

    $settingEntry = $appSettings.ChildNodes |  where key -EQ $key
    if($settingEntry -ne $null)
    {
        $settingEntry.value = $value
    }
    
    else{
        $newNode = $document.CreateElement("add")
        $newNode.SetAttribute('key', $key)
        $newNode.SetAttribute('value', $value)
        $appSettings.AppendChild($newNode)
    }
}

<#
.Description
Install nuget packages using the nuget.exe tool.
Copy binary files to the lib folder.
#>

Function InstallFrom-Nuget{
    param(
        $destination = "$PSScriptRoot",
        $packageName = "DD.QA.Ms.Powershell",
        $source = "https://proget.gmgmt.dimensiondata.com/nuget/Aperture-R2.0/",
        $ConfigFile,
        $nugetCommand = "nuget.exe"
    )
    if([string]::IsNullOrEmpty($packageName)){
    throw [System.ArgumentException]"The package name needs to be specified."
    }
    if([string]::IsNullOrEmpty($nugetCommand)){
        throw [System.ArgumentException]"The path to the nugetCommand needs to be specified."
    }
    
    Set-Alias -Name "nuget" -Value $nugetCommand

    $staging = "$destination\staging"

    if(-not (Test-Path "$staging"))
    {
        New-Item -ItemType Directory -Path "$staging"
    }

    try{
        nuget install $packageName -Source $source -OutputDirectory "$staging"
    }
    catch{
        Write-Warning $Error[0].ErrorDetails
    }


    $lib= "$destination\lib"
    if(-not (Test-Path "$lib"))
    {
        New-Item -ItemType Directory -Path "$lib"
    }

    $files = Get-ChildItem -Path $staging -Filter "*.dll" -Recurse -ErrorAction Ignore
    $files | Copy-Item -Destination "$lib"

    $pkg = "$destination\pkg"
    if(-not (Test-Path "$pkg"))
    {
        New-Item -ItemType Directory -Path "$pkg"
    }

    Get-ChildItem -Path $staging -Filter "*.nupkg" -Recurse -ErrorAction Ignore | Copy-Item -Destination "$pkg"
}