Initial release
This commit is contained in:
parent
965ee2d187
commit
5dbc75d216
3 changed files with 349 additions and 2 deletions
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/.vscode
|
||||
/lib/*
|
||||
/modules/*
|
||||
/psmodule/*
|
||||
/tmp/*
|
||||
/config/*
|
||||
/data/*
|
||||
72
README.md
72
README.md
|
|
@ -1,3 +1,71 @@
|
|||
# processing-bootstrap
|
||||
# processing bootstrap
|
||||
|
||||
Simple folder-based script execution environment designed for modularity.
|
||||
|
||||
Suitable for the automation tasks as a better alternative to a Behemoth-class monolithic scripts.
|
||||
|
||||
Script execution order is a simple alphanumeric sort by a file name. Scripts are executed from a directories with '\d+-\w+' name pattern
|
||||
|
||||
# Usage example
|
||||
|
||||
```
|
||||
- 10-init \
|
||||
10-load-environment.ps1
|
||||
|
||||
- 20-functions \
|
||||
server-connection.ps1
|
||||
data-mangling.ps1
|
||||
|
||||
- 50-exec \
|
||||
10-connect-server.ps1
|
||||
30-doing-the-needful.ps1
|
||||
99-disconnect-server.ps1
|
||||
|
||||
- config \
|
||||
server-credentials.json
|
||||
|
||||
- data \
|
||||
salsa-scheme.xml
|
||||
|
||||
start.ps1
|
||||
|
||||
```
|
||||
|
||||
# Directory structure
|
||||
|
||||
### config
|
||||
|
||||
Place configuration files here, like server names, credentials, apikeys etc.
|
||||
|
||||
Files with .json extension would be autoloaded under $BS.config.filename variable
|
||||
|
||||
### data
|
||||
|
||||
Use it for the work data like temp files and so on.
|
||||
|
||||
### psmodule
|
||||
|
||||
If you need to load specific PS modules (not installed in the system or in the user profile) then you can copy them there and they would be automatically imported by PowerShell itself through $PSModules
|
||||
|
||||
### lib
|
||||
|
||||
.NET assemblies would be autoloaded from here, place the DLLs in the net4 directory for PS5 and net7 for PwSh7+
|
||||
|
||||
### submodule
|
||||
|
||||
Place *git* submodules here
|
||||
|
||||
### docs
|
||||
|
||||
You do write the docs?
|
||||
|
||||
# Using in the other project tracked by git
|
||||
|
||||
Consider using `git submodule`:
|
||||
|
||||
```sh
|
||||
mkdir submodule
|
||||
cd submodule
|
||||
git submodule add https://$SITENAME/processing-bootstrap.git
|
||||
```
|
||||
|
||||
Simple folder-based script execution environment designed for modularity
|
||||
272
start.ps1
Normal file
272
start.ps1
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
<#
|
||||
.Synopsis
|
||||
Simple folder based script execution environment.
|
||||
|
||||
.DESCRIPTION
|
||||
Simple folder based script execution environment designed for modularity.
|
||||
|
||||
Suitable for the automation tasks as a better alternative to a Behemoth-class monolithic scripts.
|
||||
|
||||
Script execution order is a simple alphanumeric sort by the file name.
|
||||
|
||||
.EXAMPLE
|
||||
./start.ps1
|
||||
|
||||
# execute in the current directory
|
||||
|
||||
.EXAMPLE
|
||||
./start.ps1 -MainScriptRoot /mnt/tukayyid
|
||||
|
||||
# expect everything are located at the specified path
|
||||
|
||||
.EXAMPLE
|
||||
./start.ps1 -PSModule /data/ironhold/psmodule
|
||||
|
||||
# load the PS modules form the specified path
|
||||
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
# Path where the scripts and data for the execution are located
|
||||
$Root = $PSScriptRoot,
|
||||
|
||||
# Configuration storage path
|
||||
$Config,
|
||||
|
||||
# Data storage path
|
||||
$Data,
|
||||
|
||||
# .NET assemblies directory
|
||||
$Lib,
|
||||
|
||||
# PowerShell modules path (would be added to PSModulesPath for the auto-magik)
|
||||
$PSModule,
|
||||
|
||||
# Custom arguments
|
||||
[Parameter(
|
||||
ValueFromRemainingArguments=$true
|
||||
)]
|
||||
$CustomArgs
|
||||
|
||||
)
|
||||
|
||||
# this is a global variable which would be accessbile anywhere in the session
|
||||
|
||||
$global:BS = @{
|
||||
|
||||
Path = @{
|
||||
PSScriptRoot = $PSScriptRoot
|
||||
Root = $null
|
||||
}
|
||||
|
||||
Config = @{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# workaround for the interactive script launch (ie no defined $Root)
|
||||
|
||||
if ($PSBoundParameters['Root']) {
|
||||
$global:BS.Path.Root = $PSBoundParameters['Root']
|
||||
}
|
||||
else {
|
||||
$global:BS.Path.Root = $PSScriptRoot
|
||||
}
|
||||
|
||||
# add any custom args to the configuration var
|
||||
|
||||
if ($PSBoundParameters['CustomArgs']) {
|
||||
$global:BS.Config.Add('CustomArgs', $PSBoundParameters['CustomArgs'])
|
||||
}
|
||||
|
||||
# auto configure the main paths
|
||||
|
||||
# list of the variables
|
||||
@(
|
||||
'config'
|
||||
'data'
|
||||
'lib'
|
||||
'psmodule'
|
||||
) | % {
|
||||
|
||||
if ($value = $PSBoundParameters[$_]) {
|
||||
|
||||
# if this path was supplied at the start then add it as is
|
||||
|
||||
$global:BS.Path.Add($_, $value)
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
# otherwise assume it's under the main script root path
|
||||
# no attemps are made for the path validation, it's upon you
|
||||
|
||||
$global:BS.Path.Add($_, (Join-Path $BS.Path.Root $_))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Adding ./psmodule to $PSModulePath allows the module auto loading without explicitly
|
||||
# calling Import-Module with the absolute or relative paths
|
||||
# Note, if you prefer for the bundled modules not to be loaded before the ones available in the system,
|
||||
# swap '{0}{1}{2}' to '{2}{1}{0}'
|
||||
|
||||
if (Test-Path $BS.Path.PSModule) {
|
||||
|
||||
# if the path exists
|
||||
|
||||
if ($Env:PSModulePath -match [regex]::Escape($BS.Path.PSModule)) {
|
||||
|
||||
# nothing to do, the path was already in PSModulePath
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
$Env:PSModulePath = '{0}{1}{2}' -f $BS.Path.PSModule, [System.IO.Path]::PathSeparator, $Env:PSModulePath
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
# load any configiguration to the global variable
|
||||
|
||||
if (Test-Path $BS.Path.config) {
|
||||
|
||||
foreach ($file in (gci $BS.Path.config -Filter *.json)) {
|
||||
|
||||
try {
|
||||
|
||||
$json = Get-Content $file.fullname | ConvertFrom-json
|
||||
|
||||
$BS.config.add($file.basename, $json)
|
||||
|
||||
}
|
||||
catch {
|
||||
|
||||
write-warning ('Failed to load configuration data from the file "{0}"' -f $file.fullname)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# auto load .NET assemblies
|
||||
|
||||
function Register-Assembly {
|
||||
<#
|
||||
.Synopsis
|
||||
Load .NET assembly
|
||||
.DESCRIPTION
|
||||
Load .NET assembly or assemblies
|
||||
.EXAMPLE
|
||||
Register-Assembly
|
||||
|
||||
Load any .dll in the current path
|
||||
.EXAMPLE
|
||||
Register-Assembly -Path ./lib/nestandard99/kewllib.dll
|
||||
|
||||
Load a dll from the explicit path
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
[Alias('Register-Assemblies')]
|
||||
Param
|
||||
(
|
||||
|
||||
# Path to *.dll
|
||||
[Alias('AssemblyPath')]
|
||||
$Path = $PWD
|
||||
|
||||
)
|
||||
|
||||
function loadassembly {
|
||||
param ($pathToDll)
|
||||
|
||||
try {
|
||||
[System.Reflection.Assembly]::LoadFile($pathToDll)
|
||||
Write-Verbose ("Loaded assembly: {0}" -f $pathToDll)
|
||||
}
|
||||
catch {
|
||||
Write-Error $_
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$thisPath = Get-Item $Path -ErrorAction Stop
|
||||
|
||||
if ($thisPath.PSIsContainer) {
|
||||
Get-ChildItem -Filter '*.dll' | % {
|
||||
loadassembly $_.FullName
|
||||
}
|
||||
}
|
||||
|
||||
# this whould be triggered both for when PSIsContainer is false (ie this is a file) and when this property doesn't exists
|
||||
else {
|
||||
loadassembly $thisPath.FullName
|
||||
}
|
||||
|
||||
}
|
||||
Catch {
|
||||
Write-Error $_
|
||||
}
|
||||
|
||||
|
||||
} # end function Register-Assembly
|
||||
|
||||
|
||||
# $PSVersionTable.PSVersion
|
||||
|
||||
# Windows PowerShell 5.x
|
||||
if ($PSVersionTable.PSVersion.Major -eq 5) {
|
||||
$subFolder = 'net4'
|
||||
}
|
||||
|
||||
# PowerShell 6
|
||||
elseif ($PSVersionTable.PSVersion.Major -eq 6) {
|
||||
$subFolder = 'netstandard2'
|
||||
}
|
||||
|
||||
# PowerShell 7.0
|
||||
elseif ($PSVersionTable.PSVersion -lt [version]'7.2.0') {
|
||||
$subFolder = 'netstandard2'
|
||||
}
|
||||
|
||||
# PowerShell 7.2
|
||||
elseif ($PSVersionTable.PSVersion -lt [version]'7.3.0') {
|
||||
$subFolder = 'net6'
|
||||
}
|
||||
|
||||
# PowerShell 7.3+
|
||||
else {
|
||||
$subFolder = 'net7'
|
||||
}
|
||||
|
||||
$pathToLoadFrom = Join-Path $global:BS.Path.lib $subFolder
|
||||
|
||||
if (Test-Path $pathToLoadFrom) {
|
||||
Write-Verbose ("Loading .NET assemblies from the path: {0}" -f $pathToLoadFrom)
|
||||
Register-Assembly -AssemblyPath $pathToLoadFrom
|
||||
}
|
||||
|
||||
Remove-Variable subFolder, pathToLoadFrom -ErrorAction SilentlyContinue
|
||||
|
||||
# end load .NET assemblies
|
||||
|
||||
# use only dirs named like 01-Something etc
|
||||
|
||||
$dirsToProcess = gci -Path $BS.Path.Root -Directory | ? Name -Match '\d+-\w+' | Sort-Object Name
|
||||
|
||||
foreach ($thisDir in $dirsToProcess) {
|
||||
|
||||
$scriptFiles = gci $thisDir.FullName -Filter '*.ps1' | Sort-Object Name
|
||||
|
||||
foreach ($thisFile in $scriptFiles) {
|
||||
|
||||
'Processing {0}\{1}' -f $thisDir.Name, $thisFile.Name | Write-Verbose
|
||||
|
||||
. $thisFile.FullName
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue