Saturday, October 28, 2017

How to invoke a child build definition from powershell using VSTS

Get the buildid(parent and child) of the build defintions and use the powershell script to invoke the build from powershell


$buildQueUri = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/build/builds?api-version=2.0"


$parameters = @{
"system.debug" = $env:SYSTEM_DEBUG
"deploymentEnvironment" = $deploymentEnvironment
"region" = $regions
"deploymentPaths" =  $deploymentPaths
"parentBuildID" = $buildId
"requestedBy" = $requestedBy
}|ConvertTo-Json -Compress

$body = @{
"definition" = @{ "id" = $childBuildId }
"requestedFor" = @{ "id" = $env:BUILD_REQUESTEDFORID }
"sourceBranch" = $sourceBranch
"sourceVersion" = $sourceVersion
"parameters" = $parameters
}|ConvertTo-Json -Compress

$buildResponse = Invoke-RestMethod -Method Post -Uri $buildQueUri -Headers $headers -Body $body -ContentType 'application/json' -ErrorAction Stop

Saturday, October 7, 2017

Getting Azure advisor details from powershell using REST API

            
$advisorName = "Azure Advisor";            
function Invoke-AzureManagementPostMethod {            
             
 process {            
            
    $ClientId = "3fb00cf8-b7a6-42e0-bfdd-ae703499a52c"            
    $ClientSecret = "40v/urtrK+QLZzU5LalL75iNJ5wv9I4EUkygbM+6EtQ="            
                
    $TenantId = (Get-AzureRmContext).Tenant.Id            
    $Resource = "https://management.azure.com/"            
     $authData = Invoke-RestMethod -Method Post `
   -Uri "https://login.windows.net/$TenantId/oauth2/token?api-version=1.0" `
   -Body @{ "grant_type"="client_credentials"; "resource"=$Resource; "client_id"=$ClientId; "client_secret"=$ClientSecret; } `
   -ContentType "application/x-www-form-urlencoded"            
  $headers = @{"Authorization"="Bearer $($authData.access_token)"}            
  return $headers            
 }            
}            
            
function Get-AzureAdvisorRecommendations {            
param(            
    [Parameter(Mandatory=$true)][String]$SubscriptionId            
)            
            
    $method = "GET"            
    $URI = "https://management.azure.com/subscriptions/$SubscriptionId/providers/Microsoft.Advisor/recommendations?api-version=2017-03-31"            
    $managementHeaders = Invoke-AzureManagementPostMethod            
    $allRecommendations = Invoke-RestMethod -Uri $URI -Method $method -Headers $managementHeaders             
    $resourcegroupRecommendations=@{}             
            
    foreach($recommendation in $allRecommendations.Value | where { $_.properties.category -in ("HighAvailability", "Performance", "Cost")} )            
    {            
        $values = $recommendation.id.Split('/')            
        $resourceGroup = $values[4]            
        $resourceName = $values[8]            
        $recommendation = @{            
            Resource          =  $resourceName            
            Source            =  $advisorName                    
            Policy            =  $recommendation.properties.shortDescription.problem                     
            Severity          =  $recommendation.properties.impact                    
            Recommendation    =  $recommendation.properties.shortDescription.solution            
            Message           =  ""            
        }             
        $recommendationObject = New-Object PSObject -Property $recommendation            
        if($resourcegroupRecommendations.ContainsKey($resourceGroup))            
        {            
            $recommendationpreviousObject = $resourcegroupRecommendations.Get_Item($resourceGroup)            
            $resourcegroupRecommendations["$resourceGroup"] = $recommendationpreviousObject,$recommendationObject            
        }            
        else            
        {            
            $resourcegroupRecommendations.Add($resourceGroup, $recommendationObject)            
        }             
    }             
    $resourcegroupRecommendations            
                
}            
            
            
$output = Get-AzureAdvisorRecommendations (Get-AzureRmContext).Subscription.Id

Azure Key vault

Creating Key Vault and keys and secret

New-AzureRmKeyVault -VaultName 'ContosoKeyVault' -ResourceGroupName 'ContosoResourceGroup' -Location 'East Asia'

$key = Add-AzureKeyVaultKey -VaultName 'ContosoKeyVault' -Name 'ContosoFirstKey' -Destination 'Software'

$secretvalue = ConvertTo-SecureString 'Pa$$w0rd' -AsPlainText -Force

$secret = Set-AzureKeyVaultSecret -VaultName 'ContosoKeyVault' -Name 'SQLPassword' -SecretValue $secretvalue

Integration with Azure active directory

Applications that use a key vault must authenticate by using a token from Azure Active Directory. To do this, the owner of the application must first register the application in their Azure Active Directory

Authorize the application to use the key or secret

Set-AzureRmKeyVaultAccessPolicy -VaultName 'ContosoKeyVault' -ServicePrincipalName 8f8c4bbd-485b-45fd-98f7-ec6300b7b4ed -PermissionsToKeys decrypt,sign

Set-AzureRmKeyVaultAccessPolicy -VaultName 'ContosoKeyVault' -ServicePrincipalName 8f8c4bbd-485b-45fd-98f7-ec6300b7b4ed -PermissionsToSecrets Get

Regenerate the Keys

$regenerationPeriod = [System.Timespan]::FromDays(1)
$parameters = @{
VaultName = $keyVaultName
AccountResourceId = $storageAccountId
AccountName = "mystoragetest1"
ActiveKeyName = "key1"
RegenerationPeriod = $regenerationPeriod
}
Add-AzureKeyVaultManagedStorageAccount @parameters

Get-AzureKeyVaultManagedStorageAccount

Update-AzureKeyVaultManagedStorageAccountKey

Accessing the Keys from the web application


https://docs.microsoft.com/en-us/azure/key-vault/key-vault-use-from-web-application

Saturday, September 23, 2017

Generating html pages using XSLT and powershell

Powershell to create HTML files from XSLT template

$xslPath = "C:\Users\ggoudar\Desktop\xslt\template.xslt"
$outputStream = New-Object -TypeName "System.IO.MemoryStream"
$arglist = New-Object -TypeName "System.Xml.Xsl.XsltArgumentList"
$XslTransform  = New-Object -TypeName "System.Xml.Xsl.XslCompiledTransform"
$reader  = New-Object -TypeName "System.IO.StreamReader" -ArgumentList $outputStream
$XslTransform.Load($xslPath)
[xml]$XmlDocument = Get-content "C:\Users\ggoudar\Desktop\xslt\data.xml"
$XslTransform.Transform($XmlDocument,$arglist,$outputStream)
$outputStream.Position = 0L
$transformed =  $reader.ReadToEnd()
$tempFile = "$([System.IO.Path]::GetTempPath())$([Guid]::NewGuid()).html"
$null = Out-File -NoClobber -FilePath $tempFile -InputObject $transformed -Force

XSLT file for generating the summary report

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="html" indent="no"/>
  <xsl:template match="/">
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta name="description" content="" />
        <meta name="author" content="" />
        <meta charset="utf-8" />
        <title>Report</title>
        <style type="text/css">
        </style>
      </head>
      <body>
        <div class="container-fluid">
          <div class="row">
            <div class="col-sm-10 col-sm-offset-1 col-md-10 col-md-offset-1 main">
              <div class="panel panel-primary">
                <div class="panel-heading">
                  Summary - IRM
                </div>
                <div class="panel-body">
                  <xsl:for-each select="Report/Subscription">
                    <table class="table table-striped">
                      <tbody>
                        <tr>
                          <td>
                            <xsl:value-of select="@Name"/>
                            <xsl:apply-templates select="ResourceGroup"/>
                          </td>
                        </tr>
                      </tbody>
                    </table>
                  </xsl:for-each>
                </div>
              </div>
            </div>
          </div>
        </div>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="ResourceGroup">
    <xsl:variable name="nodes" select="node()"/>
    <table class="table table-striped">
      <tbody>
        <tr>
          <td>
            <xsl:for-each select="@Name">
              <xsl:value-of select="." />
              <xsl:call-template name="DisplayResourceDetails">
                <xsl:with-param name="nodes" select = "$nodes" />
              </xsl:call-template>
            </xsl:for-each>
          </td>
        </tr>
      </tbody>
    </table>
  </xsl:template>
  <xsl:template name = "DisplayResourceDetails" >
    <xsl:param name = "nodes" />
    <table class="table table-striped">
      <thead>
        <tr>
          <th>Resource Type</th>
          <th>Non-Compliant Resources</th>
          <th>Errors</th>
        </tr>
      </thead>
      <tbody>
        <xsl:for-each select="$nodes">
          <tr>
            <td>
              <xsl:value-of select="@Name"/>
            </td>
            <td>
              <xsl:value-of select="count(Resource/Policy[ValidationResult=0])"/>
            </td>
            <td>
              <xsl:value-of select="count(Resource/Policy[ValidationResult=2])"/>
            </td>
          </tr>
        </xsl:for-each>
      </tbody>
    </table>
  </xsl:template>
</xsl:stylesheet>


XSLT file for generating the detailed report


<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="html" indent="no"/>

  <xsl:template match="/">
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta name="description" content="" />
        <meta name="author" content="" />
        <meta charset="utf-8" />
        <title>Report</title>
        <style type="text/css">
        </style>
      </head>
      <body>
        <div class="container-fluid">
          <div class="row">
            <div class="col-sm-10 col-sm-offset-1 col-md-10 col-md-offset-1 main">
              <div class="panel panel-primary">
                <div class="panel-heading">
                  Report Information
                </div>
                <div class="panel-body">
                  <table class="table table-striped">
                    <tbody>
                      <tr>
                        <th>Date :</th>
                        <td>
                          <xsl:value-of select="/Report/Subscription/@Date" />
                        </td>
                      </tr>
                      <tr>
                        <th>Subscription :</th>
                        <td>
                          <xsl:value-of select="/Report/Subscription/@Name" />
                        </td>
                      </tr>
                      <tr>
                        <th>Resource Group :</th>
                        <td>
                          <xsl:value-of select="/Report/Subscription/ResourceGroup/@Name" />
                        </td>
                      </tr>
                    </tbody>
                  </table>
                </div>
              </div>
            </div>
          </div>
          <div class="row">
            <div class="col-sm-10 col-sm-offset-1 col-md-10 col-md-offset-1 main">
              <div class="panel panel-primary">
                <div class="panel-heading">
                  Summary
                </div>
                <table class="table table-striped">
                  <thead>
                    <tr>
                      <th>Resource</th>
                      <th>Resource Type</th>
                      <th>Non-Compliant Rules</th>
                      <th>Errors</th>
                    </tr>
                  </thead>
                  <tbody>
                    <xsl:for-each select="Report/Subscription/ResourceGroup/ResourceType">
                      <xsl:call-template name="DisplayResourceTyperHeader">
                        <xsl:with-param name="nodes" select = "Resource" />
                        <xsl:with-param name="resourceName" select = "@Name" />
                      </xsl:call-template>
                    </xsl:for-each>
                  </tbody>
                </table>
              </div>
            </div>
          </div>
          <xsl:for-each select="Report/Subscription/ResourceGroup/ResourceType">
            <xsl:call-template name="DisplayResourceTypeDetails">
              <xsl:with-param name="nodes" select = "Resource" />
              <xsl:with-param name="resourceName" select = "@Name" />
            </xsl:call-template>
          </xsl:for-each>
        </div>
      </body>
    </html>
  </xsl:template>
  <xsl:template name = "DisplayResourceTyperHeader" >
    <xsl:param name = "nodes" />
    <xsl:param name = "resourceName" />
    <xsl:for-each select="$nodes">
      <tr>
        <td>
          <xsl:value-of select="@Name" />
        </td>
        <td>
          <xsl:value-of select="$resourceName" />
        </td>
        <td>
          <xsl:value-of  select="count(Policy[ValidationResult=0])"/>
        </td>
        <td>
          <xsl:value-of  select="count(Policy[ValidationResult=2])"/>
        </td>
      </tr>
    </xsl:for-each>
  </xsl:template>
  <xsl:template name = "DisplayResourceTypeDetails" >
    <xsl:param name = "nodes" />
    <xsl:param name = "resourceName" />
    <xsl:for-each select="$nodes">
      <div class="row" id="{generate-id(@Name)}">
        <div class="col-sm-10 col-sm-offset-1 col-md-10 col-md-offset-1 main">
          <div class="panel panel-primary">
            <div class="panel-heading">
              <b>
                <xsl:value-of select="@Name" />
              </b>
            </div>
            <div class="panel-body">
              <div class="table-responsive">
                <table class="table table-striped">
                  <thead>
                    <tr>
                      <th>Policy</th>
                      <th>Severity</th>
                      <th>Recommendation</th>
                      <th>Message</th>
                    </tr>
                  </thead>
                  <tbody>
                    <xsl:for-each select="Policy">
                      <tr>
                        <td>
                          <xsl:value-of select="@Name" />
                        </td>
                        <td>
                          <xsl:value-of select="Severity" />
                        </td>
                        <td>
                          <xsl:value-of select="Recommendation" />
                        </td>
                        <td>
                          <xsl:value-of select="Message" />
                        </td>
                      </tr>
                    </xsl:for-each>
                  </tbody>
                </table>
              </div>
            </div>
          </div>
        </div>
      </div>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>


XML file 


<?xml version="1.0" encoding="utf-8"?>
<Report>
  <Subscription Name="Subscription1" Date="19-09-2017 14:31">
    <ResourceGroup Name="ResourceGroup1">
      <ResourceType Name = "Microsoft.Web/sites">
<Resource Name="TestResource">
 <Policy Name="testing">
<Message>Message1</Message>
<Recommendation>It is recommended to choose 64-bit platform to handle more load</Recommendation>
<Severity>Medium</Severity>
<Source>Framework</Source>
<ValidationResult>0</ValidationResult>
 </Policy>
 <Policy Name="testing">
<Message>Message2</Message>
<Recommendation>It is recommended to choose 64-bit platform to handle more load</Recommendation>
<Severity>Medium</Severity>
<Source>Framework</Source>
<ValidationResult>0</ValidationResult>
 </Policy>
            </Resource>
<Resource Name="TestResource9">
 <Policy Name="testing123">
<Message>Message3 </Message>
<Recommendation>It is recommended to choose 64-bit platform to handle more load</Recommendation>
<Severity>Medium</Severity>
<Source>Framework</Source>
<ValidationResult>0</ValidationResult>
<ValidationResultText>Not Compliant</ValidationResultText>               
 </Policy>
            </Resource>
      </ResourceType>
      <ResourceType Name = "Microsoft.ServiceFabric/Cluster">
<Resource Name="TestResource1">
 <Policy Name="testing123456">
<Message>Message4</Message>
<Recommendation>It is recommended to choose 64-bit platform to handle more load</Recommendation>
<Severity>Medium</Severity>
<Source>Framework</Source>
<ValidationResult>2</ValidationResult>
<ValidationResultText>Not Compliant</ValidationResultText>               
 </Policy>
            </Resource>
      </ResourceType>
    </ResourceGroup>
    <ResourceGroup Name="ResourceGroup2">
      <ResourceType Name = "Microsoft.Web/sites">
<Resource Name="TestResource2">
 <Policy Name="testing12390">
<Message>Expected: 'False'. Received: </Message>
<Recommendation>It is recommended to choose 64-bit platform to handle more load</Recommendation>
<Severity>Medium</Severity>
<Source>Framework</Source>
<ValidationResult>2</ValidationResult>
<ValidationResultText>Not Compliant</ValidationResultText>               
 </Policy>
            </Resource>
      </ResourceType>
      <ResourceType Name = "Microsoft.ServiceFabric/Cluster">
<Resource Name="TestResource3">
 <Policy Name="testing12312">
<Message>Expected: 'False'. Received: </Message>
<Recommendation>It is recommended to choose 64-bit platform to handle more load</Recommendation>
<Severity>Medium</Severity>
<Source>Framework</Source>
<ValidationResult>2</ValidationResult>
<ValidationResultText>Not Compliant</ValidationResultText>               
 </Policy>
            </Resource>
      </ResourceType>
    </ResourceGroup>
  </Subscription>
  <Subscription Name="Subscription2">
    <ResourceGroup Name = "ResourceGroup3">
      <ResourceType Name = "Microsoft.Web/sites">
<Resource Name="TestResource4">
 <Policy Name="testing123">
<Message>Expected: 'False'. Received: </Message>
<Recommendation>It is recommended to choose 64-bit platform to handle more load</Recommendation>
<Severity>Medium</Severity>
<Source>Framework</Source>
<ValidationResult>0</ValidationResult>
<ValidationResultText>Not Compliant</ValidationResultText>               
 </Policy>
            </Resource>
      </ResourceType>
      <ResourceType Name = "Microsoft.ServiceFabric/Cluster">
<Resource Name="TestResource5">
 <Policy Name="testing123">
<Message>Expected: 'False'. Received: </Message>
<Recommendation>It is recommended to choose 64-bit platform to handle more load</Recommendation>
<Severity>Medium</Severity>
<Source>Framework</Source>
<ValidationResult>2</ValidationResult>
<ValidationResultText>Not Compliant</ValidationResultText>               
 </Policy>
            </Resource>
      </ResourceType>
    </ResourceGroup>
    <ResourceGroup Name = "ResourceGroup4">
      <ResourceType Name = "Microsoft.Web/sites">
<Resource Name="TestResource6">
 <Policy Name="testing123">
<Message>Expected: 'False'. Received: </Message>
<Recommendation>It is recommended to choose 64-bit platform to handle more load</Recommendation>
<Severity>Medium</Severity>
<Source>Framework</Source>
<ValidationResult>2</ValidationResult>
<ValidationResultText>Not Compliant</ValidationResultText>               
 </Policy>
            </Resource>
      </ResourceType>
      <ResourceType Name = "Microsoft.ServiceFabric/Cluster">
<Resource Name="TestResource7">
 <Policy Name="testing123">
<Message>Expected: 'False'. Received: </Message>
<Recommendation>It is recommended to choose 64-bit platform to handle more load</Recommendation>
<Severity>Medium</Severity>
<Source>Framework</Source>
<ValidationResult>0</ValidationResult>
<ValidationResultText>Not Compliant</ValidationResultText>               
 </Policy>
            </Resource>
      </ResourceType>
    </ResourceGroup>
  </Subscription>
</Report>






Thursday, September 21, 2017

Rest API call to TFS to get the changeset details from the build


Getting the changeset details from VSTS

Enable the setting "Allow script to access OAuth token" in the VSTS team system and run the following powershell commands


$buildId = $env:BUILD_BUILDID

$headers = @{Authorization=("Bearer {0}" -f $env:SYSTEM_ACCESSTOKEN)}

$buildInfoUri = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/build/builds/$($buildId)?api-version=2.0"

$buildInfo = Invoke-RestMethod -Method Get -Uri $buildInfoUri -Headers $headers 

$sourceVersion = $buildInfo.sourceVersion

$changesetUrl = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)/_apis/tfvc/changesets/$($sourceVersion)/changes?api-version=2.0"

$changeset = Invoke-RestMethod -Method Get -Uri $changesetUrl -Headers $headers 

Sunday, September 17, 2017

How to trigger a azure web job from a web hook using powershell



$xmlProfile = [xml](Get-AzureRMWebAppPublishingProfile -ResourceGroupName "delete" -Name"testwebgirish" -OutputFile test.xml)
$userName = $xmlProfile.publishData.publishProfile[0].userName.Tostring()
$userPWD = $xmlProfile.publishData.publishProfile[0].userPWD.Tostring()
$url = $webJobs.url
$index = $url.IndexOf('triggeredwebjobs')
$webJobUrl = $url.Substring(0,$index+ "triggeredwebjobs/"
$webHookUrl = $webJobUrl + $webJobs.name + "/run"
$request = [System.Net.WebRequest]::Create($webHookUrl)
#$pair = "$userName"+":"+$userPWD+"
$auth =[System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($userName+":"+$userPWD))
$request.Method = "POST"
$request.ContentLength = 0;
$request.Headers["Authorization"] = "Basic " + $auth
$response = $request.GetResponse()
$responsestream = $response.GetResponseStream();
[System.IO.StreamReader] $streamReader = New-Object System.IO.StreamReader -argumentList$responsestream;
[string] $results = $streamReader.ReadToEnd();

Saturday, September 9, 2017

New features of TFS 2017

1) Code search

2) Pull request for git

3) Support for package management

4) New build editor

5) Pull based deployment without having to have a separate agent
    The agents are deployed to the target server. We can deploy to all the server or few of teh other ar create a custom one

6) Pipeline as code