Modular Development with Powershell – Part 1
Modular programming is a software design technique that emphasizes separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality. In the Devops world a lot of great code exists, mostly as independent scripts. Over a period of time, if the code is not managed correctly it becomes an administrative nightmare to manage the code and review dependencies between scripts. Every language I have worked with has one or more way to make the code modular. From Win32 API’s, C, C++, .Net, Python, Powershell we have the concept of libraries and modules that expose code functions with well defined interface. Most of the code that I have seen recently in the Devops world exists as independent script files. No coding consistency, as huge monoliths . In this article I would discuss a way to modularize your code for Powershell.
Let us see an example for the PowerShell modules
The best way I have to demonstrate an existing powershell Module is the Microsoft Azure Modules. Look at the way Microsoft has organized the code in modules exposing the functions. The below screenshot shows the Microsoft Az Modules
In the above screenshot you can see how neatly the compute related functionality is coded in the Az.Compute module, the DataFactory related functionality is organized in Az.DataFactory module.
If you look closely Powershell allows multiple module versions to co-exist and this is a great feature. You can load the differnt version of the module if one has a bug or issues.
Let us see how we can create a similar modular structure
Shown below are the files I have created to demonstrate the modular structure. Please note that I used the code available here on my Github repository. I will explain the purpose of the files.
Explaining the files created by the project
The file ‘MyTestProject-TestModule.psd1’ is a module manifest file and describes the contents of the module and determines how the module is processed. For our project this is also a module entry point. Let us see the elements/contents of this file. For more details review the Microsoft document here. I will also explain the contents in more details later in the document. Let us see the contents quickly.
Notice that I have defined a root Module element that points to the PSM1 file. The file “MyTestProject-TestModule.psm1” is a module file which defines the module exports. You can create more than one function in a module and unless you export the functions they would remain internal to the module. They will be available within the module to be used internally. I will demonstrate that in a little bit.
PowerShell allows coding functions in the same PSM1 file however I keep things neat and store files in one or more function*.ps1 files. In the list you can see that I have a file function-TestModule.PS1. If there are too many functions, to keep things neat and tidy I would create a file function-TestModule1.ps1 and so on. Remember to import all the powershell files as Ihave done in the line 17 in the screenshot above. “. $PSScriptRoot\function-TestModule1.ps1” would load the file. remember to import/load the function files before the export command as shown in Line 19 in the above screenshot. Let us review the file containing the function(s).
You may have noticed that this is a empty/dummy function. You may want to keep the structure and create your functions in the format I used.
Let us write a simple function and test it real quick.
I have changed the line 30 and made the function parameter optional by setting the Mandatory value to false. I also added the line 37. Write-Host simply prints the message. Let us test the module
I used the import-module command and provided the path to the psd1 file. This loaded the module. If you review the output for get-module command you can see that the “MyTestProject-TestModule” is loaded and it is exporting a function name New-DummyTestModule. Let us run the function since the module is loaded. I can simply run the exported command and it should show me the intended message.
Let us do another test by modifying the function a little bit. I am going to make the parmeter mandatory again and print the parameter value
Since the module is already loaded, if I run the import-module, it wont’t be reloaded unless I specify the -force directive.
You can notice that the parameter was mandatory and when I called the function it asked me to enter a value and then the value was printed. I can also enter the value as a parameter to the function as shown below and I will not be prompted
Notice how the intellisence kicks in an gives me available options.
I ran the function with the parameter
You can add more functions and decide whether you want to export them or not.
To be continued…
For feedback, comments, suggestions write to me at gsjutla@lessergeek.com