Tuesday 13 December 2016

Moveing classic resources (within subscription)

Well – according to the documentation then you can use the portal to move classic resource items around your groups.

  • Virtual machines (classic) must be moved with the cloud service.
  • Cloud service can only be moved when the move includes all its virtual machines.”

“To move classic resources to a new resource group within the same subscription, use the standard move operations through the portal, Azure PowerShell, Azure CLI, or REST API. You use the same operations as you use for moving Resource Manager resources.”

It even has a nice little picture showing it being done

I had a group with two resources – a VM and its cloud service – but the portal would not allow them to be moved.

So this nice little script does it

# prompt for credentials etc.
Login-AzureRmAccount
# select the correct subscription
Get-AzureRmSubscription -SubscriptionName "Stiona Software General" | Select-AzureRmSubscription
# get the ResourceID property of the two resources - luckily they have the same name in my case
$resources = Get-AzureRmResource -ResourceName fusionreports -ResourceGroupName fusionreports | Select -ExpandProperty ResourceId
# issue a move to the new group
Move-AzureRmResource -DestinationResourceGroupName fusionazure -ResourceId $resources

The $resources this -

/subscriptions/b9fee249-e903-4c4a-ade7-42982be9a20f/resourceGroups/fusionreports/providers/Microsoft.ClassicCompute/domainNa
mes/fusionreports
/subscriptions/b9fee249-e903-4c4a-ade7-42982be9a20f/resourceGroups/fusionreports/providers/Microsoft.ClassicCompute/virtualM
achines/fusionreports

After promt to move the old resource group was empty and the new one contained the vm and cloud service.

Nice hint from stack overflow on the use of  ExpandProperty parameter of Select-Object for getting an array of values from an array of objects.

Man – working with Azure classic sure is tough.

Monday 5 December 2016

Finding dependencies

Looking to find service references and database connections in web.config files on a server or a set of servers.

I started with this guys script - http://www.markrainey.me/2013/03/finding-urls-in-text-files.html but he was just interested in unique url’s so I hacked it around a bit and also added in another regex for the connection strings.

This is not perfect by any means but is a start for anyone else (or me in the future)

########################################################### 
# AUTHOR  : Mark Rainey  
# Ammended - Stuart McLean 2016-05-12
# DATE    : 2013-03-13  
# COMMENT : Reads in a list of servers and searches
# the E:\Live folder for config files.  When it finds
# them it searches for anything starting with 3 or more
# letters (tcp or http) followed by a colon and \\
# now also outputs connection string data and 
# looks for </value in urls
###########################################################

#ERROR REPORTING ALL
Set-StrictMode -Version latest

$scriptpath = Split-Path -parent $MyInvocation.MyCommand.Definition
# A friend at work helped me get this to output to Excel
$outputFile = $scriptpath + "\urls.csv"
$connectionFile = $scriptpath + "\connections.csv"
# This is a file with a FQDN of each server on a new line
$serverList = $scriptpath + "\serverlist.txt"
# Load server list
$servers = Get-Content $serverList


$URLS = New-Object System.Collections.ArrayList
$ConnectionStrings = New-Object System.Collections.ArrayList

$credential = Get-Credential

# Find the string and save it to a file
Function getStringMatch
{
 Try { 
  # Loop through all servers
  Foreach ($server In $servers) {
      # Set UNC Path to files for this server
   $drive = "\\" + $server + "\d$"
   New-PSDrive -Root $drive  -PSProvider FileSystem -Name z -Credential $credential
   #The path can be anywhere on your servers you want to search
   $path     = "z:\AppWebSites"
   #Get list of files
   $files    =  Get-Childitem $path web.config -Recurse | Where-Object { !($_.psiscontainer) } 
   # Loop through the server and search all config files under E:\Live
    #$matches = New-Object System.Collections.ArrayList
   #$matches.clear()
   Foreach ($file In $files)
      {
    $fullFileName = $file.FullName 
    # regular expression for a URL format
    #$regex = '([a-zA-Z]{3,})://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)*?'
    # find any urls
    $regex = '([a-zA-Z]{3,})(:\/\/.*)(?=<)'
                # Find all matches in current file and add the Value for each one to an array
    select-string -Path $fullFileName -Pattern $regex -AllMatches | % { $_.Matches } | % {
        $found = New-Object psobject -Property  @{       
        server = $server;
        urlRef = $_.Value;
        file = $file.FullName
        }
        
     $URLS.add($found)
    }

    $connectionStringRegex = '(?<=connectionString=")(.*)(?=")'
    select-string -Path $fullFileName -Pattern $connectionStringRegex -AllMatches | % { $_.Matches } | % {
    try{
        $connectionString = $_.Value;

        $source =   ($connectionString | select-string -Pattern '(?<=data source=)(.*?)(?=;)').Matches[0].Value 
        $catalog =  ($connectionString | select-string -Pattern '(?<=Initial Catalog=)(.*?)(?=;)').Matches[0].Value 
        $sqlUser =  ($connectionString | select-string -Pattern '(?<=User ID=|uid=)(.*?)(?=;)').Matches[0].Value 
        $found = New-Object psobject -Property  @{       
        server = $server;
        source = $source;
        catalog = $catalog;
        sqluser = $sqlUser;
        file = $file.FullName
        }
        
     $connectionStrings.add($found)
     }
     Catch {
  Write-host "could not parse connection string $_" + $connectionString
 }
      } 
   }
            
   Remove-PSDrive z
  
  }
  
 }
 Catch {
  Write-host "Something failed $_"
 }
 Finally {
  "Finished"
 }
 
}
  getStringMatch
  $URLS.ToArray() | Export-Csv -Path $outputFile -NoTypeInformation
  $connectionStrings.ToArray() | Export-Csv -Path $connectionFile -NoTypeInformation