My PowerShell SwissKnife & how to make your own custom one
Tags: azure, devops, powershell, scripting
Published: 2020-05-24 04:47:39

Hi my name is Mert I'm a Cloud DevOps Engineer and in this post, I would like to talk about my PowerShell Swissknife functions(I'd like to call them) and how do I use them to make my life easier for my every day tasks. My hope is to inspire some, who are not already leveraging power of scripting and automation 
just because they can do things through a graphical user interface.

## Table Of Contents
  * [Create your custom functions folder](#Create-your-custom-functions-folder)
  * [Functions](#Functions)
    * [Get-MyPublicIPAddress.ps1](#Get-MyPublicIPAddress)
    * [Set-MyAZSub.ps1](#Set-MyAZSub)
    * [New-FeatureBranchName.ps1](#New-FeatureBranchName)

## Create your custom functions folder <a name="Create-your-custom-functions-folder"></a>

First of all, you will need a folder to put all your custom script files. I keep them in under my user profile. 
Below is an example Microsoft.PowerShell_profile.ps1 that I'm using right now.  

If you don't know your profile files location, just type $profile in your Powershell Terminal and it should print out the location to you. 

```powershell
> $profile
C:\Users\Mert\Documents\PowerShell\Microsoft.PowerShell_profile.ps1
```

Below is the content of my **profile.ps1** file.  
It contains the code you need to add in order to import your custom functions and It also has the Powershell auto-complete goodies  

```powershell
# Shows navigable menu of all options when hitting Tab
Set-PSReadlineKeyHandler -Key Tab -Function MenuComplete

# Autocompletion for arrow keys
Set-PSReadlineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadlineKeyHandler -Key DownArrow -Function HistorySearchForward

#Custom functions location
$Path = "C:\Users\Mert\source\MertPSFunctions\"
Get-ChildItem -Path $Path -Filter *.ps1 |ForEach-Object {
    . $_.FullName
}
```

## Functions  <a name="Functions"></a>

### Get-MyPublicIPAddress.ps1 <a name="Get-MyPublicIPAddress"></a>

This function is a great oneliner for all purposes you would need your public IP address for. Most common scenario I have is to whitelist my client IP address temporarily while allowing an Azure resource.  

Even when you don't need your Public IP Address in a programmatically, manual way of retrieving is also very difficult.
You need to Google "What is My IP Address" and copy and paste the result, maybe even clear from HTML formatting.  

This little custom function helped me out a ton while doing my regular tasks. Enterprise level companies and their networks are not simple due to security perimeters, compliance schemes etc. So in a regular day, I might need to connect to corporate VPN whenever I need production access and then drop back out to gain more internet speed again. (We are working remotely due to COVID-19 as of writing this post)

To add on top of this, I don't get assigned same Public IP address due to our VPNs architecture which I don't know and have no interest in knowing.  

Long story short, I need to know my Public IP Address quite often some days, so this is definitely a life saver.  

<!-- Github Gist For Get-PublicIPAddress.ps1 -->
<!-- {{< gist MertSenel   >}} -->

{% gist https://gist.github.com/MertSenel/60c3a34ad91ec64e0a94410ca5f849b6 %}

### Set-MyAZSub.ps1  <a name="Set-MyAZSub"></a>

This function is a preconstructed Azure subscription list that allows you to change your PowerShell Az Module's AzContext without needing to pass in explicit Subscription or Tenant id information each time you want to change subscriptions.  

Normally this is what we do to change AzContext.  

```powershell
Set-AzContext -Subscription 'SUBSCRIPTION-NAME-OR-ID' -TenantId 'AZURE-AD-DIRECTORY-TENANT-ID'
```

But I don't want to go to Azure Portal and find a GUID or possible a second one, the tenant ID.  

When I've realized I was doing this a lot, I've created the script below so I can just jump between my subscriptions with a shorter and easy to remember way.  

So script below, needs some preparation on your end, you have to manually fill in the Subscription details, in the below hashtable. Once you have a populated table you may now change or login to your subscriptions with  

```powershell
Set-MyAzSub 'proj1-dev'
```

this small piece of code invocation. Pick 3 - 5 letter abbreviation for your projects and 3 letter codes should be enough for stages, like DEV,TST,STG. This way you will have a consistent model.  

In my case in my current role, I'm mainly responsible for 2 products that both has Development, Test, Staging subscriptions tied to my regular account(non-admin), I also have a Visual Studio Enterprise subscription where I can do proof of concepts with $200 monthly credit to spend.  

Hence changing my shell's context on the fly easily is really handy. This script also logs you in, if it doesn't detect an AzContext.

<!-- Github Gist For Set-MyAzSub.ps1 -->
{% gist https://gist.github.com/MertSenel/c3a96c8cb39caa02c93612023944ef9b %}

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/lyhp7utwduz47cxg6i0w.png)
<figcaption>The script in action</figcaption>

### New-FeatureBranchName.ps1  <a name="New-FeatureBranchName"></a>

One major change you can tell if an IT shop is doing DevOps or not, is you can tell by their infrastructure assets and if they are being provisioned as code, their scripts and everything should be treated as a software project.  

This being the case, I work closely with Backend and FrontEnd Software Developers, Test Automation Engineers and all the other parties of Software Development Lifecycle.  

We are using textbook gitflow hence all of my changes needs to be tracked by a work item in our Kanban board so it can be referenced later on. I need to come up with branch names that explains my work. This may be easy for a developer as they are used to doing it for longer then a DevOps engineer.  

We had a requirement to prefix all branch names with WorkItem ID associated, so I only had to come up some descriptive text.
This led me constructing strings (branch name) directly from work item description.  

![Gitflow](https://dev-to-uploads.s3.amazonaws.com/i/2nda1y1x279re6vxsfu7.png)
<figcaption>Gitflow</figcaption>

normally I call feature branches something like "feature/WorkItemID_WorkItemTitle"  

but sometimes if a project is in early stages there might be too many branches going active at the same time.

So I sometimes use this format so everyone knows those branches belongs to the "DevOps Guy" and possibly includes, Infrastructure, Configuration, script or something similar.  

"feature/initials/WorkItemID_WorkItemTitle"  

this way all of my branches are listed under "feature/ms/ID_Title" so their owner is visually observed easily.  

<!-- Github Gist For New-FeatureBranchName.ps1 -->
{% gist https://gist.github.com/MertSenel/1bf3b01ecbddd9b9966a7663603a1dab %}

Let's now use the script for an example let say I have to create a branch for this work item:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0looadvlqaumgw2po9e0.png)
<figcaption>This is how a Work Item looks like in Azure DevOps Boards</figcaption>

I can execute:  

```powershell
> New-FeatureBranchName -id 264 -title 'Create Azure VM via ARM Template'
feature/264_Create_Azure_VM_via_ARM_Template
#or with initials  
> New-FeatureBranchName -id 264 -title 'Create Azure VM via ARM Template' -initials ms
feature/ms/264_Create_Azure_VM_via_ARM_Template
```

and get back my feature branch name. It looks simple and it is but that is the good thing about this, I don't want to think about a simple thing, I don't want to curate a templated string value manually each time I need it, a machine can do it for me.   

Do you also have these type of small handy scripts you use in your day to day tasks?  

Around 2 years ago I started doing all the tasks asked of me scripted, even if it looks like a once off or a small simple task.  
I guarantee you, most of the time you would to either re-perform the same task or a variation of it. People provide you wrong passwords they give you wrong connection strings etc, you may have to update that KeyVault secret or AppSettings again and again.  

Scripts(code) not only performs the tasks faster, they also produce consistent results than us humans.

Although time benefited looks small, it is great practice to think in DevOps hat and look at automating as much as possible.