diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md deleted file mode 100644 index 07291c8..0000000 --- a/.github/CHANGELOG.md +++ /dev/null @@ -1,10 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [0.8.0] - -- Initial release. diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index 86af45e..7f8bc3d 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -72,4 +72,4 @@ available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.h [homepage]: https://www.contributor-covenant.org -For answers to common questions about this code of conduct, see [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq) \ No newline at end of file +For answers to common questions about this code of conduct, see [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq) diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..041b810 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,18 @@ +# Security Policy + +## Reporting a Vulnerability + + + +If you discover a vulnerability in pwshCloudCommands, please follow the _following process_: + +1. Open a generic bug issue advising you have discovered a vulnerability. + - Avoid sharing specifics or details of the vulnerability in an open GitHub issue. +2. A repo owner will reach out to you to establish a private form of communication. +3. We will evaluate the vulnerability and, if necessary, release a fix or mitigating steps to address it. We will contact you to let you know the outcome, and will credit you in the report. + + Please **do not disclose the vulnerability publicly** until a fix is released! + +4. Once we have either a) published a fix, or b) declined to address the vulnerability for whatever reason, you are free to publicly disclose it. diff --git a/.github/workflows/wf_Linux.yml b/.github/workflows/wf_Linux.yml index f44bf58..375315a 100644 --- a/.github/workflows/wf_Linux.yml +++ b/.github/workflows/wf_Linux.yml @@ -5,13 +5,18 @@ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions # https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-powershell # https://github.com/actions/upload-artifact#where-does-the-upload-go -# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-including-branches name: pwshCloudCommands-Linux on: pull_request: + paths-ignore: + - '**.md' + - 'docs/**' branches-ignore: - 'pipeline' push: + paths-ignore: + - '**.md' + - 'docs/**' branches-ignore: - 'pipeline' jobs: @@ -22,7 +27,7 @@ jobs: fail-fast: false steps: - name: Check out repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Display the path shell: pwsh run: echo ${env:PATH} @@ -40,14 +45,15 @@ jobs: shell: pwsh run: Invoke-Build -File .\src\pwshCloudCommands.build.ps1 - name: Upload pester results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: pester-results path: ./src/Artifacts/testOutput if-no-files-found: warn - name: Upload zip module archive build - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: zip-archive path: ./src/Archive if-no-files-found: warn + diff --git a/.github/workflows/wf_MacOS.yml b/.github/workflows/wf_MacOS.yml index fcd7fbe..dfd54a6 100644 --- a/.github/workflows/wf_MacOS.yml +++ b/.github/workflows/wf_MacOS.yml @@ -5,13 +5,18 @@ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions # https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-powershell # https://github.com/actions/upload-artifact#where-does-the-upload-go -# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-including-branches name: pwshCloudCommands-MacOS on: pull_request: + paths-ignore: + - '**.md' + - 'docs/**' branches-ignore: - 'pipeline' push: + paths-ignore: + - '**.md' + - 'docs/**' branches-ignore: - 'pipeline' jobs: @@ -22,7 +27,7 @@ jobs: fail-fast: false steps: - name: Check out repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Display the path shell: pwsh run: echo ${env:PATH} @@ -40,14 +45,15 @@ jobs: shell: pwsh run: Invoke-Build -File .\src\pwshCloudCommands.build.ps1 - name: Upload pester results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: pester-results path: ./src/Artifacts/testOutput if-no-files-found: warn - name: Upload zip module archive build - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: zip-archive path: ./src/Archive if-no-files-found: warn + diff --git a/.github/workflows/wf_Windows.yml b/.github/workflows/wf_Windows.yml index d296e07..473bf6b 100644 --- a/.github/workflows/wf_Windows.yml +++ b/.github/workflows/wf_Windows.yml @@ -5,13 +5,18 @@ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions # https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-powershell # https://github.com/actions/upload-artifact#where-does-the-upload-go -# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-including-branches name: pwshCloudCommands-Windows on: pull_request: + paths-ignore: + - '**.md' + - 'docs/**' branches-ignore: - 'pipeline' push: + paths-ignore: + - '**.md' + - 'docs/**' branches-ignore: - 'pipeline' jobs: @@ -22,7 +27,7 @@ jobs: fail-fast: false steps: - name: Check out repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Display the path shell: powershell run: echo ${env:PATH} @@ -46,14 +51,15 @@ jobs: shell: powershell run: Invoke-Build -File .\src\pwshCloudCommands.build.ps1 - name: Upload pester results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: pester-results path: .\src\Artifacts\testOutput if-no-files-found: warn - name: Upload zip module archive build - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: zip-archive path: .\src\Archive if-no-files-found: warn + diff --git a/.github/workflows/wf_Windows_Core.yml b/.github/workflows/wf_Windows_Core.yml index 958cb3a..7c9e1d1 100644 --- a/.github/workflows/wf_Windows_Core.yml +++ b/.github/workflows/wf_Windows_Core.yml @@ -5,13 +5,18 @@ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions # https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-powershell # https://github.com/actions/upload-artifact#where-does-the-upload-go -# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-including-branches name: pwshCloudCommands-Windows-pwsh on: pull_request: + paths-ignore: + - '**.md' + - 'docs/**' branches-ignore: - 'pipeline' push: + paths-ignore: + - '**.md' + - 'docs/**' branches-ignore: - 'pipeline' jobs: @@ -22,7 +27,7 @@ jobs: fail-fast: false steps: - name: Check out repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Display the path shell: pwsh run: echo ${env:PATH} @@ -40,14 +45,15 @@ jobs: shell: pwsh run: Invoke-Build -File .\src\pwshCloudCommands.build.ps1 - name: Upload pester results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: pester-results path: .\src\Artifacts\testOutput if-no-files-found: warn - name: Upload zip module archive build - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: zip-archive path: .\src\Archive if-no-files-found: warn + diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..76d1c23 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,25 @@ +# https://docs.readthedocs.io/en/stable/config-file/index.html + +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +mkdocs: + configuration: mkdocs.yml + +python: + install: + - requirements: docs/requirements.txt + +# # Build PDF & ePub +formats: all +# - epub +# - pdf diff --git a/.vscode/settings.json b/.vscode/settings.json index 73e3859..b919bd1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,18 +1,28 @@ { + "markdownlint.config": { + "default": true, + "MD007": { + "indent": 4 + }, + "no-hard-tabs": false + }, // When enabled, will trim trailing whitespace when you save a file. "files.trimTrailingWhitespace": true, // specifies the PowerShell coding style used in this project (https://github.com/PoshCode/PowerShellPracticeAndStyle/issues/81) "powershell.codeFormatting.preset": "Stroustrup", "cSpell.words": [ "ACCOUNTID", + "autopagination", "Backoff", "bucketname", "buildspec", + "Catesta", "childtemplates", "Clixml", "controlplane", "Datapoints", "datapull", + "datetime", "Deduplication", "discoverability", "dotnetcore", @@ -34,9 +44,11 @@ "pwshcloudcommands", "Redrive", "sqseval", + "testbucket", "xmldatafiles" ], "cSpell.enableFiletypes": [ + "!yaml", "powershell" ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 6c6b55f..f6898a9 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -4,7 +4,7 @@ // Available variables which can be used inside of strings. // https://code.visualstudio.com/docs/editor/variables-reference#_predefined-variables // ${workspaceFolder}: path of the folder opened in VS Code -// pwshCloudCommands - name of the folder opened in VS Code without any slashes (/) +// ${workspaceFolderBasename} - name of the folder opened in VS Code without any slashes (/) // ${file}: current opened file // ${fileWorkspaceFolder} - current opened file's workspace folder // ${relativeFile}: the current opened file relative to workspaceFolder @@ -61,7 +61,7 @@ { "label": ".", "type": "shell", - "command": "$PSVersionTable;Invoke-Build -Task . -File '${workspaceFolder}/src/pwshCloudCommands.build.ps1'", + "command": "$PSVersionTable;Invoke-Build -Task . -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", "problemMatcher": "$msCompile", "presentation": { "echo": false, @@ -75,7 +75,7 @@ { "label": "TestLocal", "type": "shell", - "command": "Invoke-Build -Task TestLocal -File '${workspaceFolder}/src/pwshCloudCommands.build.ps1'", + "command": "Invoke-Build -Task TestLocal -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", "problemMatcher": "$msCompile", "presentation": { "echo": false, @@ -86,7 +86,7 @@ { "label": "HelpLocal", "type": "shell", - "command": "Invoke-Build -Task HelpLocal -File '${workspaceFolder}/src/pwshCloudCommands.build.ps1'", + "command": "Invoke-Build -Task HelpLocal -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", "problemMatcher": "$msCompile", "presentation": { "echo": false, @@ -97,7 +97,7 @@ { "label": "Clean", "type": "shell", - "command": "Invoke-Build -Task Clean -File '${workspaceFolder}/src/pwshCloudCommands.build.ps1'", + "command": "Invoke-Build -Task Clean -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", "problemMatcher": "$msCompile", "presentation": { "echo": false, @@ -108,7 +108,7 @@ { "label": "ValidateRequirements", "type": "shell", - "command": "Invoke-Build -Task ValidateRequirements -File '${workspaceFolder}/src/pwshCloudCommands.build.ps1'", + "command": "Invoke-Build -Task ValidateRequirements -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", "problemMatcher": "$msCompile", "presentation": { "echo": false, @@ -120,7 +120,7 @@ "label": "Analyze", "type": "shell", "problemMatcher": "$msCompile", - "command": "Invoke-Build -Task Analyze -File '${workspaceFolder}/src/pwshCloudCommands.build.ps1'", + "command": "Invoke-Build -Task Analyze -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", "presentation": { "echo": false, "showReuseMessage": false @@ -130,7 +130,7 @@ { "label": "AnalyzeTests", "type": "shell", - "command": "Invoke-Build -Task AnalyzeTests -File '${workspaceFolder}/src/pwshCloudCommands.build.ps1'", + "command": "Invoke-Build -Task AnalyzeTests -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", "problemMatcher": "$msCompile", "presentation": { "echo": false, @@ -141,7 +141,7 @@ { "label": "FormattingCheck", "type": "shell", - "command": "Invoke-Build -Task FormattingCheck -File '${workspaceFolder}/src/pwshCloudCommands.build.ps1'", + "command": "Invoke-Build -Task FormattingCheck -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", "problemMatcher": "$msCompile", "presentation": { "echo": false, @@ -152,7 +152,7 @@ { "label": "Test", "type": "shell", - "command": "Invoke-Build -Task Test -File '${workspaceFolder}/src/pwshCloudCommands.build.ps1'", + "command": "Invoke-Build -Task Test -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", "problemMatcher": "$msCompile", "presentation": { "echo": false, @@ -163,7 +163,7 @@ { "label": "DevCC", "type": "shell", - "command": "Invoke-Build -Task DevCC -File '${workspaceFolder}/src/pwshCloudCommands.build.ps1'", + "command": "Invoke-Build -Task DevCC -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", "problemMatcher": "$msCompile", "presentation": { "echo": false, @@ -174,7 +174,7 @@ { "label": "Build", "type": "shell", - "command": "Invoke-Build -Task Build -File '${workspaceFolder}/src/pwshCloudCommands.build.ps1'", + "command": "Invoke-Build -Task Build -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", "problemMatcher": "$msCompile", "presentation": { "echo": false, @@ -183,9 +183,9 @@ "group": "none" }, { - "label": "BuildNoInfra", + "label": "BuildNoIntegration", "type": "shell", - "command": "Invoke-Build -Task BuildNoInfra -File '${workspaceFolder}/src/pwshCloudCommands.build.ps1'", + "command": "Invoke-Build -Task BuildNoIntegration -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", "problemMatcher": "$msCompile", "presentation": { "echo": false, @@ -194,9 +194,9 @@ "group": "build" }, { - "label": "InfraTest", + "label": "IntegrationTest", "type": "shell", - "command": "Invoke-Build -Task InfraTest -File '${workspaceFolder}/src/pwshCloudCommands.build.ps1'", + "command": "Invoke-Build -Task IntegrationTest -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", "problemMatcher": "$msCompile", "presentation": { "echo": false, @@ -207,14 +207,14 @@ { "label": "PesterTest", "type": "shell", - "command": "Invoke-Pester '${workspaceFolder}/src/Tests/Unit' -PesterOption @{IncludeVSCodeMarker=$true}", + "command": "Invoke-Pester '${workspaceFolder}/src/Tests/Unit' -Output Detailed", "problemMatcher": "$pester", "group": "test" }, { "label": "Pester-Single-Coverage", "type": "shell", - "command": "Import-Module -Name '${workspaceFolder}/src/pwshCloudCommands/pwshCloudCommands.psm1';Invoke-Pester '${workspaceFolder}/src/Tests/Unit/${input:functionName}.Tests.ps1' -CodeCoverage '${workspaceFolder}/src/pwshCloudCommands/*/${input:functionName}.ps1'", + "command": "Import-Module -Name '${workspaceFolder}/src/${workspaceFolderBasename}/${workspaceFolderBasename}.psm1';$pesterConfig = New-PesterConfiguration;$pesterConfig.run.Path = '${workspaceFolder}/src/Tests/Unit/*/${input:functionName}.Tests.ps1';$pesterConfig.CodeCoverage.Enabled = $true;$pesterConfig.CodeCoverage.Path = '${workspaceFolder}/src/${workspaceFolderBasename}/*/${input:functionName}.ps1';Invoke-Pester -Configuration $pesterConfig", "problemMatcher": "$pester", "presentation": { "echo": false, @@ -225,7 +225,7 @@ { "label": "Pester-Single-Detailed", "type": "shell", - "command": "Import-Module -Name '${workspaceFolder}/src/pwshCloudCommands/pwshCloudCommands.psm1';Invoke-Pester '${workspaceFolder}/src/Tests/Unit/${input:functionName}.Tests.ps1' -Output Detailed", + "command": "Import-Module -Name '${workspaceFolder}/src/${workspaceFolderBasename}/${workspaceFolderBasename}.psm1';Invoke-Pester '${workspaceFolder}/src/Tests/Unit/*/${input:functionName}.Tests.ps1' -Output Detailed", "problemMatcher": "$pester", "presentation": { "echo": false, @@ -236,7 +236,18 @@ { "label": "DevCC-Single", "type": "shell", - "command": "Import-Module -Name '${workspaceFolder}/src/pwshCloudCommands/pwshCloudCommands.psm1';Invoke-Pester '${workspaceFolder}/src/Tests/Unit/${input:functionName}.Tests.ps1' -CodeCoverage '${workspaceFolder}/src/pwshCloudCommands/*/${input:functionName}.ps1' -CodeCoverageOutputFile '${workspaceFolder}/cov.xml'", + "command": "Import-Module -Name '${workspaceFolder}/src/${workspaceFolderBasename}/${workspaceFolderBasename}.psm1';$pesterConfig = New-PesterConfiguration;$pesterConfig.run.Path = '${workspaceFolder}/src/Tests/Unit/*/${input:functionName}.Tests.ps1';$pesterConfig.CodeCoverage.Enabled = $true;$pesterConfig.CodeCoverage.Path = '${workspaceFolder}/src/${workspaceFolderBasename}/*/${input:functionName}.ps1';$pesterConfig.CodeCoverage.OutputPath = '${workspaceFolder}/cov.xml';$pesterConfig.CodeCoverage.OutputFormat = 'CoverageGutters';Invoke-Pester -Configuration $pesterConfig", + "problemMatcher": "$pester", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "test" + }, + { + "label": "Integration-Single-Detailed", + "type": "shell", + "command": "Import-Module -Name '${workspaceFolder}/src/${workspaceFolderBasename}/${workspaceFolderBasename}.psm1';Invoke-Pester '${workspaceFolder}/src/Tests/Integration/*/${input:functionName}.Tests.ps1' -Output Detailed", "problemMatcher": "$pester", "presentation": { "echo": false, @@ -253,3 +264,4 @@ } ] } + diff --git a/CodeBuild/IntegrationTest/Tests/Integration.Tests.ps1 b/CodeBuild/IntegrationTest/Tests/Integration.Tests.ps1 index 20b9f1b..f22e6b2 100644 --- a/CodeBuild/IntegrationTest/Tests/Integration.Tests.ps1 +++ b/CodeBuild/IntegrationTest/Tests/Integration.Tests.ps1 @@ -1,8 +1,9 @@ +# $env:SERVICE_NAME = name of the project # $env:ARTIFACT_S3_BUCKET = the artifact bucket used by CB -# $env:S3_PREFIX = the artifact prefix used by CB -# $env:GIT_REPO = the git repo name # $env:AWS_ACCOUNTID = the AWS Account hosting the service under test -# $env:SERVICE_NAME = name of the project +# $env:GIT_REPO = the git repo name +# $env:S3_PREFIX = the artifact prefix used by CB + Describe -Name 'Infrastructure Tests' -Fixture { BeforeAll { @@ -49,4 +50,20 @@ Describe -Name 'Infrastructure Tests' -Fixture { } #context_pscc_ssm.yml + Context -Name 'pscc_alarms.yml' -Fixture { + + It -Name 'Should create a pwshCCPubXMLMonitorAlarmARN' -Test { + $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-pwshCCPubXMLMonitorAlarmARN" }).Value + $expected = 'arn:aws:cloudwatch:*' + $assertion | Should -BeLike $expected + } #it + + It -Name 'Should create a pwshCCPubXMLMonitorARN' -Test { + $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-pwshCCPubXMLMonitorARN" }).Value + $expected = 'arn:aws:lambda:*' + $assertion | Should -BeLike $expected + } #it + + } #context_pscc_alarms.yml + } #describe_infra_tests diff --git a/CodeBuild/IntegrationTest/buildspec.yml b/CodeBuild/IntegrationTest/buildspec.yml index c1d3064..758613c 100644 --- a/CodeBuild/IntegrationTest/buildspec.yml +++ b/CodeBuild/IntegrationTest/buildspec.yml @@ -8,7 +8,7 @@ version: 0.2 phases: install: runtime-versions: - dotnet: 5.0 + dotnet: 6.0 commands: - echo Configure AWS defaults using the configuration script added to the Docker Image. diff --git a/CodeBuild/UnitTestAndBuild/buildspec.yml b/CodeBuild/UnitTestAndBuild/buildspec.yml index 2474959..e0bc35d 100644 --- a/CodeBuild/UnitTestAndBuild/buildspec.yml +++ b/CodeBuild/UnitTestAndBuild/buildspec.yml @@ -8,7 +8,7 @@ version: 0.2 phases: install: runtime-versions: - dotnet: 5.0 + dotnet: 6.0 # python: 3.9 commands: @@ -59,12 +59,12 @@ phases: # Run Python unit tests # - python -m pytest lambdafunctions/python/tests -v - # Running Invoke-Build against each PowerShell AWS Lambda Function - # - pwsh -command 'Import-Module -Name "AWS.Tools.Common"; Get-ChildItem -Path './lambdafunctions/pwsh' -Filter '*.build.ps1' -File -Recurse | ForEach-Object {Invoke-Build -File $_.FullName}' - # Publish cloudformation templates to S3 - pwsh -command '& ./CodeBuild/UnitTestAndBuild/Publish-CFNTemplatesToS3.ps1' + # Running Invoke-Build against each PowerShell AWS Lambda Function + - pwsh -command 'Get-ChildItem -Path './lambdafunctions/PowerShell' -Filter '*.build.ps1' -File -Recurse | ForEach-Object {Invoke-Build -File $_.FullName}' + - cd $CODEBUILD_SRC_DIR/cloudformation - aws cloudformation package --template-file controlplane.yml --s3-bucket $ARTIFACT_S3_BUCKET --output-template-file controlplane-packaged.yml @@ -75,4 +75,4 @@ phases: artifacts: files: - cloudformation/**/* - - CodeBuild/**/* \ No newline at end of file + - CodeBuild/**/* diff --git a/CodeBuild/configure_aws_credential.ps1 b/CodeBuild/configure_aws_credential.ps1 index 85c8f7b..a815f95 100644 --- a/CodeBuild/configure_aws_credential.ps1 +++ b/CodeBuild/configure_aws_credential.ps1 @@ -6,7 +6,7 @@ .NOTES This script enables AWSPowerShell cmdlets in your CodeBuild to interact with and access other AWS resources in your account. #> -'Configurating AWS credentials' +'Configuring AWS credentials' ' - Retrieving temporary credentials from metadata' $uri = 'http://169.254.170.2{0}' -f $env:AWS_CONTAINER_CREDENTIALS_RELATIVE_URI @@ -24,4 +24,4 @@ $null = New-Item -Path $credentialsFile -Force ' - Setting default AWS Region' 'region={0}' -f $env:AWS_DEFAULT_REGION | Out-File -FilePath $credentialsFile -Append -' - AWS credentials configured' \ No newline at end of file +' - AWS credentials configured' diff --git a/CodeBuild/install_modules.ps1 b/CodeBuild/install_modules.ps1 index dc84cb5..ab5d55c 100644 --- a/CodeBuild/install_modules.ps1 +++ b/CodeBuild/install_modules.ps1 @@ -7,7 +7,7 @@ need to specify each module and version that is required for installation. You also need to specify which version of that module should be installed. Additionally, you will need to specify the S3 bucket location where that module currently resides, so that it can be downloaded and installed into the build - container at runtime. This neccessitates that you download and upload your required modules to S3 prior to + container at runtime. This necessitates that you download and upload your required modules to S3 prior to the build being executed. .EXAMPLE Save-Module -Name Pester -RequiredVersion 4.4.5 -Path C:\RequiredModules @@ -20,118 +20,125 @@ #> +$galleryDownload = $true + $ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' $VerbosePreference = 'SilentlyContinue' -$galleryDownload = $false # set to false to download from S3 - # List of PowerShell Modules required for the build # The AWS PowerShell Modules are added below, based on the $PSEdition $modulesToInstall = [System.Collections.ArrayList]::new() # https://github.com/pester/Pester $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'Pester' - ModuleVersion = '5.3.1' - BucketName = 'ps-invoke-modules' + ModuleVersion = '5.5.0' + BucketName = 'PSGallery' KeyPrefix = '' })) $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'InvokeBuild' - ModuleVersion = '5.9.7' - BucketName = 'ps-invoke-modules' + ModuleVersion = '5.10.4' + BucketName = 'PSGallery' KeyPrefix = '' })) $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'PSScriptAnalyzer' - ModuleVersion = '1.20.0' - BucketName = 'ps-invoke-modules' - KeyPrefix = '' - })) -$null = $modulesToInstall.Add(([PSCustomObject]@{ - ModuleName = 'Convert' - ModuleVersion = '0.6.0' - BucketName = 'ps-invoke-modules' + ModuleVersion = '1.21.0' + BucketName = 'PSGallery' KeyPrefix = '' })) $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'PoshGram' - ModuleVersion = '2.0.0' - BucketName = 'ps-invoke-modules' - KeyPrefix = '' - })) -$null = $modulesToInstall.Add(([PSCustomObject]@{ - ModuleName = 'PackageManagement' - ModuleVersion = '1.4.7' - BucketName = 'ps-invoke-modules' - KeyPrefix = '' - })) -$null = $modulesToInstall.Add(([PSCustomObject]@{ - ModuleName = 'PowerShellGet' - ModuleVersion = '2.2.5' - BucketName = 'ps-invoke-modules' + ModuleVersion = '2.3.0' + BucketName = 'PSGallery' KeyPrefix = '' })) $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'AWSLambdaPSCore' - ModuleVersion = '3.0.0.0' - BucketName = 'ps-invoke-modules' + ModuleVersion = '3.0.1.0' + BucketName = 'PSGallery' KeyPrefix = '' })) $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'AWS.Tools.Common' - ModuleVersion = '4.1.30.0' - BucketName = 'ps-invoke-modules' + ModuleVersion = '4.1.472' + BucketName = 'PSGallery' KeyPrefix = '' })) $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'AWS.Tools.CloudFormation' - ModuleVersion = '4.1.30.0' - BucketName = 'ps-invoke-modules' + ModuleVersion = '4.1.472' + BucketName = 'PSGallery' KeyPrefix = '' })) $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'AWS.Tools.S3' - ModuleVersion = '4.1.30.0' - BucketName = 'ps-invoke-modules' - KeyPrefix = '' - })) -$null = $modulesToInstall.Add(([PSCustomObject]@{ - ModuleName = 'AWS.Tools.SecretsManager' - ModuleVersion = '4.1.30.0' - BucketName = 'ps-invoke-modules' + ModuleVersion = '4.1.472' + BucketName = 'PSGallery' KeyPrefix = '' })) $null = $modulesToInstall.Add(([PSCustomObject]@{ - ModuleName = 'AWS.Tools.SQS' - ModuleVersion = '4.1.30.0' - BucketName = 'ps-invoke-modules' + ModuleName = 'AWS.Tools.SimpleSystemsManagement' + ModuleVersion = '4.1.472' + BucketName = 'PSGallery' KeyPrefix = '' })) -$tempPath = [System.IO.Path]::GetTempPath() -if ($PSVersionTable.Platform -eq 'Win32NT') { - $moduleInstallPath = [System.IO.Path]::Combine($env:ProgramFiles, 'WindowsPowerShell', 'Modules') - if ($PSEdition -eq 'Core') { - $moduleInstallPath = [System.IO.Path]::Combine($env:ProgramFiles, 'PowerShell', 'Modules') +if ($galleryDownload -eq $false) { + + $tempPath = [System.IO.Path]::GetTempPath() + + if ($PSVersionTable.Platform -eq 'Win32NT') { + $moduleInstallPath = [System.IO.Path]::Combine($env:ProgramFiles, 'WindowsPowerShell', 'Modules') + if ($PSEdition -eq 'Core') { + $moduleInstallPath = [System.IO.Path]::Combine($env:ProgramFiles, 'PowerShell', 'Modules') + # Add the AWSPowerShell.NetCore Module + # $null = $modulesToInstall.Add(([PSCustomObject]@{ + # ModuleName = 'AWSPowerShell.NetCore' + # ModuleVersion = '3.3.604.0' + # BucketName = 'PSGallery' + # KeyPrefix = '' + # })) + } + else { + $moduleInstallPath = [System.IO.Path]::Combine($env:ProgramFiles, 'WindowsPowerShell', 'Modules') + # Add the AWSPowerShell Module + # $null = $modulesToInstall.Add(([PSCustomObject]@{ + # ModuleName = 'AWSPowerShell' + # ModuleVersion = '3.3.604.0' + # BucketName = 'PSGallery' + # KeyPrefix = '' + # })) + } + } + elseif ($PSVersionTable.Platform -eq 'Unix') { + $moduleInstallPath = [System.IO.Path]::Combine('/', 'usr', 'local', 'share', 'powershell', 'Modules') + + # Add the AWSPowerShell.NetCore Module + # $null = $modulesToInstall.Add(([PSCustomObject]@{ + # ModuleName = 'AWSPowerShell.NetCore' + # ModuleVersion = '3.3.604.0' + # BucketName = 'PSGallery' + # KeyPrefix = '' + # })) } - else { + elseif ($PSEdition -eq 'Desktop') { $moduleInstallPath = [System.IO.Path]::Combine($env:ProgramFiles, 'WindowsPowerShell', 'Modules') + # Add the AWSPowerShell Module + # $null = $modulesToInstall.Add(([PSCustomObject]@{ + # ModuleName = 'AWSPowerShell' + # ModuleVersion = '3.3.604.0' + # BucketName = 'PSGallery' + # KeyPrefix = '' + # })) + } + else { + throw 'Unrecognized OS platform' } -} -elseif ($PSVersionTable.Platform -eq 'Unix') { - $moduleInstallPath = [System.IO.Path]::Combine('/', 'usr', 'local', 'share', 'powershell', 'Modules') -} -elseif ($PSEdition -eq 'Desktop') { - $moduleInstallPath = [System.IO.Path]::Combine($env:ProgramFiles, 'WindowsPowerShell', 'Modules') -} -else { - throw 'Unrecognized OS platform' -} -if ($galleryDownload -eq $false) { - 'Installing PowerShell Modules from S3' + 'Installing PowerShell Modules' foreach ($module in $modulesToInstall) { ' - {0} {1}' -f $module.ModuleName, $module.ModuleVersion @@ -163,25 +170,30 @@ if ($galleryDownload -eq $false) { } #if_GalleryDownload else { Get-PackageProvider -Name Nuget -ForceBootstrap | Out-Null - 'Installing PowerShell Modules from PSGallery' + 'Installing PowerShell Modules' Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted # $NuGetProvider = Get-PackageProvider -Name "NuGet" -ErrorAction SilentlyContinue # if ( -not $NugetProvider ) { # Install-PackageProvider -Name "NuGet" -Confirm:$false -Force -Verbose # } foreach ($module in $modulesToInstall) { + $installSplat = @{ + Name = $module.ModuleName + RequiredVersion = $module.ModuleVersion + Repository = 'PSGallery' + SkipPublisherCheck = $true + Force = $true + ErrorAction = 'Stop' + } try { - if ($module.ModuleName -eq 'Pester' -and $PSEdition -eq 'Desktop') { - Install-Module $module.ModuleName -RequiredVersion $module.ModuleVersion -Repository PSGallery -Force -SkipPublisherCheck -ErrorAction Stop - } - else { - Install-Module $module.ModuleName -RequiredVersion $module.ModuleVersion -Repository PSGallery -Confirm:$false -Force -ErrorAction Stop - } + Install-Module @installSplat + Import-Module -Name $module.ModuleName -ErrorAction Stop + ' - Successfully installed {0}' -f $module.ModuleName } catch { $message = 'Failed to install {0}' -f $module.ModuleName " - $message" - throw $_ + throw } } } diff --git a/LICENSE b/LICENSE index 374ad61..c836c15 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Jake Morrison +Copyright (c) 2024 Jake Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 49dcfa0..030eed1 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Branch | Windows - PowerShell | Windows - pwsh | Linux | MacOS --- | --- | --- | --- | --- | main | [![Build status Windows PowerShell main](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Windows.yml/badge.svg?branch=main)](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Windows.yml) | [![Build Status Windows pwsh main](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Windows_Core.yml/badge.svg?branch=main)](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Windows_Core.yml) | [![Build Status Linux main](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Linux.yml/badge.svg?branch=main)](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Linux.yml) | [![Build Status MacOS main](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_MacOS.yml/badge.svg?branch=main)](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_MacOS.yml) -Enhancements | [![Build status Windows PowerShell Enhancements](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Windows.yml/badge.svg?branch=Enhancements)](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Windows.yml) | [![Build Status Windows pwsh Enhancements](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Windows_Core.yml/badge.svg?branch=Enhancements)](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Windows_Core.yml) | [![Build Status Linux Enhancements](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Linux.yml/badge.svg?branch=Enhancements)](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Linux.yml) | [![Build Status MacOS Enhancements](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_MacOS.yml/badge.svg?branch=Enhancements)](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_MacOS.yml) +Enhancements | [![pwshCloudCommands-Windows](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Windows.yml/badge.svg?branch=Enhancements)](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Windows.yml) | [![pwshCloudCommands-Windows-pwsh](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Windows_Core.yml/badge.svg?branch=Enhancements)](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Windows_Core.yml) | [![pwshCloudCommands-Linux](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Linux.yml/badge.svg?branch=Enhancements)](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_Linux.yml) | [![pwshCloudCommands-MacOS](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_MacOS.yml/badge.svg?branch=Enhancements)](https://github.com/techthoughts2/pwshCloudCommands/actions/workflows/wf_MacOS.yml) ## Synopsis @@ -17,38 +17,32 @@ Search, discover, and identify PowerShell cloud commands across multiple cloud p ## Description -pwshCloudCommands enables you to search for and discover PowerShell cloud commands and functions without the need to save or install modules locally. -It uses a cloud-based, event driven workflow to generate a dynamic cache of known PowerShell cloud commands. -This cache can be searched, queried, and leveraged to identify what functions and modules are being used inside your project. -You can use pwshCloudCommands to: +pwshCloudCommands is a PowerShell module that simplifies the search and analysis of cloud-specific PowerShell commands, without the need to install cloud modules locally. It provides a dual discovery method: querying cloud commands across AWS, Azure, and Oracle, and scanning local project files to identify which cloud commands and modules are being utilized. -* Search for and discover PowerShell cloud commands across multiple cloud providers. -* Scan your existing project files to identify all used PowerShell cloud commands and their corresponding module. +### Features -[pwshCloudCommands](docs/pwshCloudCommands.md) provides the following functions: +- Fully cross-platform and can be run on Windows, Linux, and macOS +- Module-Free Command Search: Discover PowerShell commands without the need for local module installations. + - Exact Function Name Search: Find specific functions, like Write-S3Object. + - Wildcard Search: Use patterns, such as New*VM*, to locate commands. + - Free-Form Search: Enter natural language queries like 'I want to create a new compute instance' for intuitive searching. +- Complete Cache Data Dump: Access a comprehensive dump containing all known PowerShell cloud commands for detailed analysis. +- Project File Analysis: Scan files and folders in your projects to identify used cloud functions and modules, crucial for project setup, discovery, and CI/CD pipeline integration. -* [Find-CloudCommand](docs/Find-CloudCommand.md) -* [Get-AllCloudCommandInfo](docs/Get-AllCloudCommandInfo.md) -* [Get-CloudCommandFromFile](docs/Get-CloudCommandFromFile.md) +## Getting Started -## Why +### Documentation -Enable easier discoverability of PowerShell cloud commands. +Documentation for pwshCloudCommands is available at: [https://pwshCloudCommands.readthedocs.io](https://pwshCloudCommands.readthedocs.io) -## Installation - -### Prerequisites - -* [PowerShell 5.1](https://github.com/PowerShell/PowerShell) *(or higher version)* - -### Installing pwshCloudCommands via PowerShell Gallery +### Installation ```powershell -#from a 5.1+ PowerShell session +# Install pwshCloudCommands from the PowerShell Gallery Install-Module -Name 'pwshCloudCommands' -Scope CurrentUser ``` -## Quick start +### Quick start ```powershell #------------------------------------------------------------------------------------------------ @@ -83,24 +77,14 @@ Get-AllCloudCommandInfo -Filter Oracle #------------------------------------------------------------------------------------------------ ``` -## Author - -[Jake Morrison](https://twitter.com/JakeMorrison) - [https://www.techthoughts.info/](https://www.techthoughts.info/) - ## Notes -PowerShell cloud information is provided via a [Cache creation component](docs/pwshCloudCommands_cache_workflow.md) - This PowerShell project was created with [Catesta](https://github.com/techthoughts2/Catesta). -## FAQ +## Contributing -[pwshCloudCommands - FAQ](docs/pwshCloudCommands-FAQ.md) +If you'd like to contribute to pwshCloudCommands, please see the [contribution guidelines](.github/CONTRIBUTING.md). ## License This project is [licensed under the MIT License](LICENSE). - -## Changelog - -Reference the [Changelog](.github/CHANGELOG.md) diff --git a/actions_bootstrap.ps1 b/actions_bootstrap.ps1 index a918b18..7d876be 100644 --- a/actions_bootstrap.ps1 +++ b/actions_bootstrap.ps1 @@ -8,21 +8,20 @@ Set-PSRepository -Name PSGallery -InstallationPolicy Trusted # List of PowerShell Modules required for the build $modulesToInstall = [System.Collections.ArrayList]::new() - # https://github.com/pester/Pester $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'Pester' - ModuleVersion = '5.3.1' + ModuleVersion = '5.5.0' })) # https://github.com/nightroman/Invoke-Build $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'InvokeBuild' - ModuleVersion = '5.8.8' + ModuleVersion = '5.10.4' })) # https://github.com/PowerShell/PSScriptAnalyzer $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'PSScriptAnalyzer' - ModuleVersion = '1.20.0' + ModuleVersion = '1.21.0' })) # https://github.com/PowerShell/platyPS # older version used due to: https://github.com/PowerShell/platyPS/issues/457 @@ -34,7 +33,7 @@ $null = $modulesToInstall.Add(([PSCustomObject]@{ # older version used due to: https://github.com/PowerShell/platyPS/issues/457 $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'Convert' - ModuleVersion = '0.6.0' + ModuleVersion = '1.5.0' })) diff --git a/cloudformation/childtemplates/pscc.yml b/cloudformation/childtemplates/pscc.yml index e9f307a..6b1c93e 100644 --- a/cloudformation/childtemplates/pscc.yml +++ b/cloudformation/childtemplates/pscc.yml @@ -10,9 +10,14 @@ Parameters: Type: String Description: The name of the service being deployed. Used for Developer AWS Account Resource Names. - StackTag: + ResourceType: Type: String - Description: An environment tag for this stack. Used to differentiate what resource need or should be created. + Description: Determine the type of resource that will be deployed + AllowedValues: + - core + - dev + - test + - prod Resources: # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html @@ -72,10 +77,10 @@ Resources: Tags: - Key: ServiceName Value: !Ref ServiceName - - Key: StackTag - Value: !Ref StackTag - Key: StackName Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType # VersioningConfiguration: # VersioningConfiguration # WebsiteConfiguration: @@ -98,21 +103,21 @@ Resources: PolicyDocument: Version: '2012-10-17' Statement: - - Action: - - s3:GetObject - Effect: Allow + - Sid: 'AllowCloudFrontServicePrincipalReadOnly' + Effect: 'Allow' Principal: - AWS: - !Join - - '' - - - 'arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ' - - !Ref PSCCCloudFrontOriginAccessIdentity - Resource: !Join - - '' - - - !GetAtt - - PSCCFinalXMLBucket - - Arn - - /* + Service: 'cloudfront.amazonaws.com' + Action: 's3:GetObject' + Resource: !Sub 'arn:${AWS::Partition}:s3:::${PSCCFinalXMLBucket}/*' + Condition: + StringEquals: + 'AWS:SourceArn': !Sub 'arn:${AWS::Partition}:cloudfront::${AWS::AccountId}:distribution/${PSCCCloudFrontDistribution}' + # - Sid: 'AllowLegacyOAIReadOnly' + # Effect: 'Allow' + # Principal: + # AWS: !Sub 'arn:${AWS::Partition}:iam::cloudfront:user/CloudFront Origin Access Identity ${PSCCCloudFrontOriginAccessIdentity}' + # Action: 's3:GetObject' + # Resource: !Sub 'arn:${AWS::Partition}:s3:::${PSCCFinalXMLBucket}/*' # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-publicaccessblockconfiguration.html @@ -149,8 +154,8 @@ Resources: # LoggingConfiguration: # DestinationBucketName: !Ref StaticWebSiteLoggingBucket # LogFilePrefix: '/logs/website/' - # MetricsConfigurations: - # - MetricsConfiguration + MetricsConfigurations: + - Id: EntireBucket # NotificationConfiguration: # TopicConfigurations: # - @@ -171,10 +176,10 @@ Resources: Tags: - Key: ServiceName Value: !Ref ServiceName - - Key: StackTag - Value: !Ref StackTag - Key: StackName Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType # VersioningConfiguration: # VersioningConfiguration # WebsiteConfiguration: @@ -204,13 +209,27 @@ Resources: Resource: - !Sub 'arn:aws:s3:::${PSCCCloudFrontLogBucket}/AWSLogs/${AWS::AccountId}/*' + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-originaccesscontrol.html + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-originaccesscontrol-originaccesscontrolconfig.html + # https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html + # https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-origin.html + PSCCCloudFrontOriginAccessControl: + Type: AWS::CloudFront::OriginAccessControl + Properties: + OriginAccessControlConfig: + Description: pwshCloudCommands CloudFront Origin Access Control + Name: pscc-origin-access-control + OriginAccessControlOriginType: s3 + SigningBehavior: always + SigningProtocol: sigv4 + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-PSCCCloudFrontOriginAccessIdentity.html # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-PSCCCloudFrontOriginAccessIdentity-PSCCCloudFrontOriginAccessIdentityconfig.html - PSCCCloudFrontOriginAccessIdentity: - Type: "AWS::CloudFront::CloudFrontOriginAccessIdentity" - Properties: - CloudFrontOriginAccessIdentityConfig: - Comment: !Ref PSCCFinalXMLBucket + # PSCCCloudFrontOriginAccessIdentity: + # Type: "AWS::CloudFront::CloudFrontOriginAccessIdentity" + # Properties: + # CloudFrontOriginAccessIdentityConfig: + # Comment: !Ref PSCCFinalXMLBucket # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-distribution.html # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distribution-distributionconfig.html @@ -278,10 +297,15 @@ Resources: # OriginGroups: # OriginGroups Origins: - - DomainName: !GetAtt "PSCCFinalXMLBucket.DomainName" - Id: s3origin + - Id: s3origin + DomainName: !GetAtt PSCCFinalXMLBucket.DomainName S3OriginConfig: - OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${PSCCCloudFrontOriginAccessIdentity}" + OriginAccessIdentity: '' + OriginAccessControlId: !GetAtt PSCCCloudFrontOriginAccessControl.Id + # - DomainName: !GetAtt "PSCCFinalXMLBucket.DomainName" + # Id: s3origin + # S3OriginConfig: + # OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${PSCCCloudFrontOriginAccessIdentity}" PriceClass: PriceClass_100 # Restrictions: # Restrictions @@ -293,10 +317,10 @@ Resources: Tags: - Key: ServiceName Value: !Ref ServiceName - - Key: StackTag - Value: !Ref StackTag - Key: StackName Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType Outputs: PSCCFinalXMLBucketName: diff --git a/cloudformation/childtemplates/pscc_alarms.yml b/cloudformation/childtemplates/pscc_alarms.yml new file mode 100644 index 0000000..c696bc0 --- /dev/null +++ b/cloudformation/childtemplates/pscc_alarms.yml @@ -0,0 +1,254 @@ +--- +AWSTemplateFormatVersion: '2010-09-09' + +Description: 'AUTOMATED: pwshCloudCommands - alarms deployment' + +Transform: 'AWS::Serverless-2016-10-31' + +Parameters: + ServiceName: + Type: String + Description: The name of the service being deployed. Used for Developer AWS Account Resource Names. + + LambdaS3BucketName: + Type: String + Description: The S3 Bucket holding the Lambda code + + LMFunctionS3KeypwshCCPubXMLMonitor: + Type: String + Description: S3 Key for the PubXMLMonitor Lambda function(s) zip file + + LMFunctionHandlerpwshCCPubXMLMonitor: + Type: String + Description: PubXMLMonitor Lambda HANDLER provided by New-AWSPowerShellLambdaPackage during build + + ResourceType: + Type: String + Description: Determine the type of resource that will be deployed + AllowedValues: + - core + - dev + - test + - prod + +Resources: + # https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html + # https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-eventsource.html + # https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-cloudwatchevent.html + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-events-rule.html#cfn-events-rule-eventpattern + pwshCCPubXMLMonitor: + Type: 'AWS::Serverless::Function' + Properties: + # Architectures: x86_64 + # AssumeRolePolicyDocument: JSON + # AutoPublishAlias: String + # AutoPublishCodeSha256: String + # CodeSigningConfigArn: String + CodeUri: + Bucket: !Ref LambdaS3BucketName + Key: !Ref LMFunctionS3KeypwshCCPubXMLMonitor + # DeadLetterQueue: Map | DeadLetterQueue + # DeploymentPreference: DeploymentPreference + Description: 'Determines age of PubXML and sends to CloudWatch Metric' + Environment: + Variables: + S3_BUCKET_NAME: !ImportValue pwshcloudcommands-PSCCFinalXMLBucket + SERVICE_NAME: !Ref ServiceName + # EphemeralStorage: EphemeralStorage + # EventInvokeConfig: EventInvokeConfiguration + # Events: EventSource + # FileSystemConfigs: List + # FunctionName: + # FunctionUrlConfig: FunctionUrlConfig + Handler: !Ref LMFunctionHandlerpwshCCPubXMLMonitor + # ImageConfig: ImageConfig + # ImageUri: String + # InlineCode: String + # KmsKeyArn: String + # Layers: List + MemorySize: 768 + # PackageType: String + # PermissionsBoundary: String + Policies: + - AWSLambdaBasicExecutionRole + - CloudWatchPutMetricPolicy: {} + - S3CrudPolicy: + BucketName: !ImportValue pwshcloudcommands-PSCCFinalXMLBucket + - SSMParameterReadPolicy: + ParameterName: telegramtoken + - SSMParameterReadPolicy: + ParameterName: telegramchannel + # ProvisionedConcurrencyConfig: ProvisionedConcurrencyConfig + # ReservedConcurrentExecutions: Integer + # Role: String + # RolePath: String + Runtime: dotnet6 + # RuntimeManagementConfig: RuntimeManagementConfig + # SnapStart: SnapStart + Tags: + ServiceName: !Ref ServiceName + StackName: !Ref AWS::StackName + ResourceType: !Ref ResourceType + Events: + RateSchedule: + Type: Schedule + Properties: + Enabled: true + Schedule: 'rate(1 day)' + Timeout: 60 + + #https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html + pwshCCPubXMLMonitorLogGroup: + Type: AWS::Logs::LogGroup + DependsOn: pwshCCPubXMLMonitor + DeletionPolicy: Delete + UpdateReplacePolicy: Retain + Properties: + # KmsKeyId: String + LogGroupName: !Sub '/aws/lambda/${pwshCCPubXMLMonitor}' + RetentionInDays: 14 + Tags: + - Key: ServiceName + Value: !Ref ServiceName + - Key: StackName + Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType + + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html + pwshCCPubXMLMonitorAlarm: + Type: AWS::CloudWatch::Alarm + Properties: + ActionsEnabled: true + AlarmActions: + - !ImportValue AlertSNSTopic + AlarmDescription: Alarms if the PubXML file is more than 8 days old. + AlarmName: pwshCCPubXMLMonitor + ComparisonOperator: GreaterThanOrEqualToThreshold + # DatapointsToAlarm: Integer + # EvaluateLowSampleCountPercentile: String + Dimensions: + - Name: PubXML + Value: DaysOld + EvaluationPeriods: 1 + # ExtendedStatistic: String + # InsufficientDataActions: + # - String + MetricName: PubXMLAge + # Metrics: + # - MetricDataQuery + Namespace: pwshCloudCommands + # OKActions: + # - String + Period: 3600 + Statistic: Maximum + Threshold: 8 + # ThresholdMetricId: String + TreatMissingData: notBreaching + # Unit: String + + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-dashboard.html + pwshCCPubXMLMonitorDashboard: + Type: AWS::CloudWatch::Dashboard + Properties: + DashboardName: !Sub '${ServiceName}-pwshCCPubXMLMonitorDashboard' + DashboardBody: !Sub | + { + "widgets": [ + { + "height": 12, + "width": 7, + "y": 0, + "x": 0, + "type": "metric", + "properties": { + "metrics": [ + [ + "pwshCloudCommands", + "PubXMLAge", + "PubXML", + "DaysOld", + { + "region": "us-west-2", + "label": "Data Cache Age (Days)" + } + ] + ], + "view": "timeSeries", + "stacked": false, + "region": "us-west-2", + "period": 86400, + "stat": "Maximum", + "start": "-P90D", + "end": "P0D", + "annotations": { + "horizontal": [ + { + "label": "Cache > 8 Days", + "value": 8 + } + ] + }, + "yAxis": { + "left": { + "label": "Days Old", + "min": 0 + }, + "right": { + "label": "Date" + } + }, + "title": "pwshCloudCommands Data Cache Age Metric" + } + }, + { + "height": 12, + "width": 6, + "y": 0, + "x": 7, + "type": "metric", + "properties": { + "metrics": [ + [ + "AWS/CloudFront", + "Requests", + "Region", + "Global", + "DistributionId", + "E2C5YCYVS84449", + { + "region": "us-east-1" + } + ] + ], + "view": "timeSeries", + "stacked": false, + "region": "us-west-2", + "period": 86400, + "stat": "Sum", + "start": "-P90D", + "end": "P0D", + "title": "Data Cache Download Requests", + "yAxis": { + "left": { + "label": "Download Count", + "min": 0 + } + } + } + } + ] + } + +Outputs: + pwshCCPubXMLMonitorARN: + Description: Arn for PubXMLMonitor Lambda + Value: !GetAtt pwshCCPubXMLMonitor.Arn + Export: + Name: !Sub ${ServiceName}-pwshCCPubXMLMonitorARN + + pwshCCPubXMLMonitorAlarmARN: + Description: PubXMLMonitorAlarm Alarm ARN + Value: !GetAtt pwshCCPubXMLMonitorAlarm.Arn + Export: + Name: !Sub ${ServiceName}-pwshCCPubXMLMonitorAlarmARN diff --git a/cloudformation/childtemplates/pscc_ssm.yml b/cloudformation/childtemplates/pscc_ssm.yml index ac52ddc..61c1582 100644 --- a/cloudformation/childtemplates/pscc_ssm.yml +++ b/cloudformation/childtemplates/pscc_ssm.yml @@ -8,51 +8,56 @@ Parameters: Type: String Description: The name of the service being deployed. Used for Developer AWS Account Resource Names. - StackTag: + ResourceType: Type: String - Description: An environment tag for this stack. Used to differentiate what resource need or should be created. + Description: Determine the type of resource that will be deployed + AllowedValues: + - core + - dev + - test + - prod Resources: - # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html - SSMHybridWorkerRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Version: '2012-10-17' - Statement: - - Effect: Allow - Principal: - Service: ssm.amazonaws.com - Action: - - sts:AssumeRole - Path: / - ManagedPolicyArns: - - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore - - arn:aws:iam::aws:policy/CloudWatchFullAccess - Policies: - - PolicyName: PSCCFinalXMLAccess - PolicyDocument: - Version: '2012-10-17' - Statement: - - Effect: Allow - Action: - - s3:PutObject - - s3:ListBucketMultipartUploads - - s3:DeleteObjectVersion - - s3:ListBucketVersions - - s3:ListBucket - - s3:DeleteObject - - s3:ListMultipartUploadParts - Resource: - - !Sub - - 'arn:aws:s3:::${FinalXMLBucket}' - - FinalXMLBucket: - 'Fn::ImportValue': !Sub ${ServiceName}-PSCCFinalXMLBucket - - !Sub - - 'arn:aws:s3:::${FinalXMLBucket}/*' - - FinalXMLBucket: - 'Fn::ImportValue': !Sub ${ServiceName}-PSCCFinalXMLBucket + # # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html + # SSMHybridWorkerRole: + # Type: AWS::IAM::Role + # Properties: + # AssumeRolePolicyDocument: + # Version: '2012-10-17' + # Statement: + # - Effect: Allow + # Principal: + # Service: ssm.amazonaws.com + # Action: + # - sts:AssumeRole + # Path: / + # ManagedPolicyArns: + # - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore + # - arn:aws:iam::aws:policy/CloudWatchFullAccess + # Policies: + # - PolicyName: PSCCFinalXMLAccess + # PolicyDocument: + # Version: '2012-10-17' + # Statement: + # - Effect: Allow + # Action: + # - s3:PutObject + # - s3:ListBucketMultipartUploads + # - s3:DeleteObjectVersion + # - s3:ListBucketVersions + # - s3:ListBucket + # - s3:DeleteObject + # - s3:ListMultipartUploadParts + # Resource: + # - !Sub + # - 'arn:aws:s3:::${FinalXMLBucket}' + # - FinalXMLBucket: + # 'Fn::ImportValue': !Sub ${ServiceName}-PSCCFinalXMLBucket + # - !Sub + # - 'arn:aws:s3:::${FinalXMLBucket}/*' + # - FinalXMLBucket: + # 'Fn::ImportValue': !Sub ${ServiceName}-PSCCFinalXMLBucket # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html @@ -107,7 +112,7 @@ Resources: Action: - sns:Publish Resource: - - !Sub arn:aws:sns:us-west-2:${AWS::AccountId}:alertTopic + - !Sub arn:${AWS::Partition}:sns:us-west-2:${AWS::AccountId}:alertTopic # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-maintenancewindow.html PSCCMaintWindow: @@ -127,10 +132,10 @@ Resources: Tags: - Key: ServiceName Value: !Ref ServiceName - - Key: StackTag - Value: !Ref StackTag - Key: StackName Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-maintenancewindowtarget.html # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-maintenancewindowtarget-targets.html @@ -183,7 +188,7 @@ Resources: # DocumentHashType: String # DocumentVersion: String NotificationConfig: - NotificationArn: !Sub arn:aws:sns:us-west-2:${AWS::AccountId}:alertTopic + NotificationArn: !Sub arn:${AWS::Partition}:sns:us-west-2:${AWS::AccountId}:alertTopic NotificationEvents: - TimedOut - Cancelled @@ -211,6 +216,8 @@ Resources: # #https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html PSCCSSMRunCommandLogGroup: Type: AWS::Logs::LogGroup + DeletionPolicy: Delete + UpdateReplacePolicy: Retain Properties: # KmsKeyId: String LogGroupName: '/aws/ssm/PSCCSSMRunCommandLogGroup' @@ -218,10 +225,10 @@ Resources: Tags: - Key: ServiceName Value: !Ref ServiceName - - Key: StackTag - Value: !Ref StackTag - Key: StackName Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType Outputs: PSCCMaintWindowID: diff --git a/cloudformation/control_plane_parameters/parameters.json b/cloudformation/control_plane_parameters/parameters.json index 58262fa..54de9ce 100644 --- a/cloudformation/control_plane_parameters/parameters.json +++ b/cloudformation/control_plane_parameters/parameters.json @@ -1,8 +1,9 @@ { "Parameters": { "ServiceName": "pwshcloudcommands", - "StackTag": "production", + "LMFunctionS3KeypwshCCPubXMLMonitor": "< This value is replace by the UnitTestAndBuild CodeBuild step in the Lambda's build file >", + "LMFunctionHandlerpwshCCPubXMLMonitor": "< This value is replace by the UnitTestAndBuild CodeBuild step in the Lambda's build file >", "ArtifactS3Bucket": "will be replaced during CodeBuild process", "ArtifactS3KeyPrefix": "will be replaced during CodeBuild process" } -} \ No newline at end of file +} diff --git a/cloudformation/controlplane.yml b/cloudformation/controlplane.yml index c5f9729..104c5a9 100644 --- a/cloudformation/controlplane.yml +++ b/cloudformation/controlplane.yml @@ -16,9 +16,13 @@ Parameters: Type: String Description: The name of the service being deployed. - StackTag: + LMFunctionS3KeypwshCCPubXMLMonitor: Type: String - Description: An environment tag for this stack. Used to differentiate what resource need or should be created. + Description: S3 Key for the PubXMLMonitor Lambda function(s) zip file + + LMFunctionHandlerpwshCCPubXMLMonitor: + Type: String + Description: PubXMLMonitor Lambda HANDLER provided by New-AWSPowerShellLambdaPackage during build ArtifactS3Bucket: Type: String @@ -39,12 +43,10 @@ Resources: TimeoutInMinutes: 25 #make sure it can actually complete in this time period Parameters: #much match the parameters of nested template ServiceName: !Ref ServiceName - StackTag: !Ref StackTag + ResourceType: prod Tags: - Key: ServiceName Value: !Ref ServiceName - - Key: StackTag - Value: !Ref StackTag - Key: StackName Value: !Ref AWS::StackName @@ -56,11 +58,27 @@ Resources: TimeoutInMinutes: 15 #make sure it can actually complete in this time period Parameters: #much match the parameters of nested template ServiceName: !Ref ServiceName - StackTag: !Ref StackTag + ResourceType: prod + Tags: + - Key: ServiceName + Value: !Ref ServiceName + - Key: StackName + Value: !Ref AWS::StackName + + PSCCAlarm: + Type: AWS::CloudFormation::Stack + DependsOn: PSCC + Properties: + TemplateURL: ./childtemplates/pscc_alarms.yml + TimeoutInMinutes: 15 #make sure it can actually complete in this time period + Parameters: #much match the parameters of nested template + ServiceName: !Ref ServiceName + LambdaS3BucketName: !Ref ArtifactS3Bucket + LMFunctionS3KeypwshCCPubXMLMonitor: !Ref LMFunctionS3KeypwshCCPubXMLMonitor + LMFunctionHandlerpwshCCPubXMLMonitor: !Ref LMFunctionHandlerpwshCCPubXMLMonitor + ResourceType: prod Tags: - Key: ServiceName Value: !Ref ServiceName - - Key: StackTag - Value: !Ref StackTag - Key: StackName Value: !Ref AWS::StackName diff --git a/cloudformation/manual/pwshCloudCommands_pipeline.yml b/cloudformation/manual/pwshCloudCommands_pipeline.yml index 14c9a24..8b7e890 100644 --- a/cloudformation/manual/pwshCloudCommands_pipeline.yml +++ b/cloudformation/manual/pwshCloudCommands_pipeline.yml @@ -51,16 +51,45 @@ Parameters: Type: String Description: The name of the GitHub user or organization who owns the GitHub repository. - GitHubBranchName: + BranchName: Type: String - Default: main + Default: pipeline Description: The name of the branch where source changes are to be detected. + CodeBuildTimeoutInMinutes: + Type: Number + Default: 30 + Description: The number of minutes before a CodeBuild build will timeout. + + # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-compute-types.html + CodeBuildEnvironment: + Type: String + Default: LINUX_CONTAINER + Description: The type of build environment. + AllowedValues: + - WINDOWS_SERVER_2019_CONTAINER + - WINDOWS_CONTAINER + - LINUX_CONTAINER + + # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-compute-types.html + CodeBuildComputeType: + Type: String + Default: BUILD_GENERAL1_SMALL + Description: The size of the CodeBuild instance. (Windows Containers do NOT support small) + AllowedValues: + - BUILD_GENERAL1_SMALL + - BUILD_GENERAL1_MEDIUM + - BUILD_GENERAL1_LARGE + + # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html CodeBuildImage: Type: String - Description: AWS CodeBuild Image Identifier - Default: aws/codebuild/standard:5.0 - AllowedPattern: ^aws\/codebuild\/standard:\d.\d$ + Default: aws/codebuild/standard:6.0 + Description: AWS CodeBuild image selection + AllowedValues: + - aws/codebuild/standard:6.0 + - aws/codebuild/amazonlinux2-x86_64-standard:4.0 + - aws/codebuild/windows-base:2019-2.0 PathToUnitTestAndBuildBuildSpecTemplate: Type: String @@ -82,6 +111,16 @@ Parameters: Description: 'The GitHub Repository path to the Control Plane Parameters JSON file' Default: cloudformation/control_plane_parameters/parameters.json + ResourceType: + Type: String + Default: prod + Description: Determine the type of resource that will be deployed + AllowedValues: + - core + - dev + - test + - prod + Metadata: AWS::CloudFormation::Interface: ParameterGroups: @@ -95,11 +134,18 @@ Metadata: - CodeStarSourceConnection - GitHubRepositoryName - GitHubOwner - - GitHubBranchName + - BranchName - Label: - default: Pipeline Configuration + default: CodeBuild Parameters: + # - PathToBuildSpecTemplate + - CodeBuildTimeoutInMinutes + - CodeBuildEnvironment + - CodeBuildComputeType - CodeBuildImage + - Label: + default: Pipeline Configuration + Parameters: - PathToUnitTestAndBuildBuildSpecTemplate - PathToIntegrationTestBuildSpecTemplate - PathToControlPlaneTemplate @@ -113,10 +159,16 @@ Metadata: default: GitHub Repository Name GitHubOwner: default: GitHub User Name - GitHubBranchName: + BranchName: default: GitHub Branch Name + CodeBuildTimeoutInMinutes: + default: CodeBuild Timeout in minutes + CodeBuildEnvironment: + default: CodeBuild Environment + CodeBuildComputeType: + default: CodeBuild Compute Type CodeBuildImage: - default: CodeBuild Image Identifier + default: CodeBuild Image Resources: # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kms-key.html @@ -133,7 +185,7 @@ Resources: - Sid: Allows administration of the KMS Key Effect: Allow Principal: - AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root' + AWS: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' Action: - 'kms:CancelKeyDeletion' - 'kms:Create*' @@ -151,11 +203,13 @@ Resources: - 'kms:Revoke*' - 'kms:ScheduleKeyDeletion' - 'kms:Update*' + - 'kms:TagResource' + - 'kms:UntagResource' Resource: '*' - Effect: Allow Principal: AWS: - - !Sub 'arn:aws:iam::${AWS::AccountId}:root' + - !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' Action: - 'kms:Encrypt' - 'kms:Decrypt' @@ -172,6 +226,8 @@ Resources: Value: !Ref ServiceName - Key: StackName Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kms-alias.html KMSAlias: @@ -235,6 +291,8 @@ Resources: Value: !Ref ServiceName - Key: StackName Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType # VersioningConfiguration: # VersioningConfiguration # WebsiteConfiguration: @@ -252,10 +310,10 @@ Resources: Effect: Allow Principal: AWS: - - !Sub 'arn:aws:iam::${AWS::AccountId}:root' + - !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' Resource: - - !Sub 'arn:aws:s3:::${pwshCloudCommandsArtifactS3Bucket}' - - !Sub 'arn:aws:s3:::${pwshCloudCommandsArtifactS3Bucket}/*' + - !Sub 'arn:${AWS::Partition}:s3:::${pwshCloudCommandsArtifactS3Bucket}' + - !Sub 'arn:${AWS::Partition}:s3:::${pwshCloudCommandsArtifactS3Bucket}/*' # - Sid: DenyUnEncryptedObjectUploads # Effect: Deny # Principal: '*' @@ -287,13 +345,21 @@ Resources: CodeBuildRole: Type: AWS::IAM::Role Properties: + RoleName: !Sub '${ServiceName}-CodeBuildRole' + Tags: + - Key: ServiceName + Value: !Ref ServiceName + - Key: StackName + Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: 'Allow' Principal: AWS: - - !Sub 'arn:aws:iam::${AWS::AccountId}:root' # Allow assuming this role for local developer testing + - !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root' # Allow assuming this role for local developer testing Service: - 'codebuild.amazonaws.com' Action: @@ -319,7 +385,9 @@ Resources: - 'logs:CreateLogStream' - 'logs:PutLogEvents' Resource: - - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/* + - !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/* + - !GetAtt UnitTestAndBuildLogGroup.Arn + - !GetAtt IntegrationTestProjectLogGroup.Arn - Effect: 'Allow' Action: - 's3:PutObject' @@ -327,9 +395,9 @@ Resources: - 's3:GetObjectVersion' - 's3:ListBucket' Resource: - - !Sub 'arn:aws:s3:::codepipeline-${AWS::Region}-*' - - !Sub 'arn:aws:s3:::${pwshCloudCommandsArtifactS3Bucket}' - - !Sub 'arn:aws:s3:::${pwshCloudCommandsArtifactS3Bucket}/*' + - !Sub 'arn:${AWS::Partition}:s3:::codepipeline-${AWS::Region}-*' + - !Sub 'arn:${AWS::Partition}:s3:::${pwshCloudCommandsArtifactS3Bucket}' + - !Sub 'arn:${AWS::Partition}:s3:::${pwshCloudCommandsArtifactS3Bucket}/*' - Effect: 'Allow' Action: - 's3:GetObject' @@ -355,63 +423,23 @@ Resources: Resource: - '*' - # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html - PSModuleAccess: - Type: AWS::IAM::Policy + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html + UnitTestAndBuildLogGroup: + Type: AWS::Logs::LogGroup + DeletionPolicy: Delete + UpdateReplacePolicy: Retain Properties: - Roles: - - !Ref CodeBuildRole - PolicyName: 'PSModuleAccess' - PolicyDocument: - Version: '2012-10-17' - Statement: - - Effect: Allow - Action: - - s3:GetAccessPoint - - s3:GetLifecycleConfiguration - - s3:GetBucketTagging - - s3:GetInventoryConfiguration - - s3:GetObjectVersionTagging - - s3:ListBucketVersions - - s3:GetBucketLogging - - s3:GetAccelerateConfiguration - - s3:GetBucketPolicy - - s3:GetObjectVersionTorrent - - s3:GetObjectAcl - - s3:GetEncryptionConfiguration - - s3:GetBucketObjectLockConfiguration - - s3:GetBucketRequestPayment - - s3:GetAccessPointPolicyStatus - - s3:GetObjectVersionAcl - - s3:GetObjectTagging - - s3:GetMetricsConfiguration - - s3:GetBucketPublicAccessBlock - - s3:GetBucketPolicyStatus - - s3:ListBucketMultipartUploads - - s3:GetObjectRetention - - s3:GetBucketWebsite - - s3:GetJobTagging - - s3:ListAccessPoints - - s3:ListJobs - - s3:GetBucketVersioning - - s3:GetBucketAcl - - s3:GetObjectLegalHold - - s3:GetBucketNotification - - s3:GetReplicationConfiguration - - s3:ListMultipartUploadParts - - s3:GetObject - - s3:GetObjectTorrent - - s3:GetAccountPublicAccessBlock - - s3:DescribeJob - - s3:GetBucketCORS - - s3:GetAnalyticsConfiguration - - s3:GetObjectVersionForReplication - - s3:GetBucketLocation - - s3:GetAccessPointPolicy - - s3:GetObjectVersion" - Resource: - - 'arn:aws:s3:::ps-invoke-modules' - - 'arn:aws:s3:::ps-invoke-modules/*' + # DataProtectionPolicy: Json + # KmsKeyId: String + LogGroupName: !Sub ${ServiceName}-UnitTestAndBuildLogGroup + RetentionInDays: 7 + Tags: + - Key: ServiceName + Value: !Ref ServiceName + - Key: StackName + Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codebuild-project.html # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-environment.html @@ -435,8 +463,8 @@ Resources: EncryptionKey: !GetAtt KMSKey.Arn Environment: # Certificate: - ComputeType: BUILD_GENERAL1_SMALL #3GB Memory | 2 vCPU | 64GB HD - Type: LINUX_CONTAINER + ComputeType: !Ref CodeBuildComputeType + Type: !Ref CodeBuildEnvironment Image: !Ref CodeBuildImage EnvironmentVariables: - Name: ARTIFACT_S3_BUCKET @@ -460,6 +488,11 @@ Resources: # - Source # SecondarySourceVersions: # - ProjectSourceVersion + LogsConfig: + CloudWatchLogs: + GroupName: !Ref UnitTestAndBuildLogGroup + Status: ENABLED + # StreamName: String ServiceRole: !GetAtt CodeBuildRole.Arn Source: # Auth: @@ -485,6 +518,26 @@ Resources: Value: !Ref ServiceName - Key: StackName Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType + + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html + IntegrationTestProjectLogGroup: + Type: AWS::Logs::LogGroup + DeletionPolicy: Delete + UpdateReplacePolicy: Retain + Properties: + # DataProtectionPolicy: Json + # KmsKeyId: String + LogGroupName: !Sub ${ServiceName}-IntegrationTestProjectLogGroup + RetentionInDays: 7 + Tags: + - Key: ServiceName + Value: !Ref ServiceName + - Key: StackName + Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codebuild-project.html IntegrationTestProject: @@ -502,8 +555,8 @@ Resources: EncryptionKey: !GetAtt KMSKey.Arn Environment: # Certificate: - ComputeType: BUILD_GENERAL1_SMALL #3GB Memory | 2 vCPU | 64GB HD - Type: LINUX_CONTAINER + ComputeType: !Ref CodeBuildComputeType + Type: !Ref CodeBuildEnvironment Image: !Ref CodeBuildImage EnvironmentVariables: - Name: ARTIFACT_S3_BUCKET @@ -516,7 +569,11 @@ Resources: Value: !Ref 'AWS::AccountId' - Name: SERVICE_NAME Value: !Ref ServiceName - # LogsConfig: + LogsConfig: + CloudWatchLogs: + GroupName: !Ref IntegrationTestProjectLogGroup + Status: ENABLED + # StreamName: String Name: !Sub '${ServiceName}-IntegrationTest' # QueuedTimeoutInMinutes: Integer # SecondaryArtifacts: @@ -550,12 +607,21 @@ Resources: Value: !Ref ServiceName - Key: StackName Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html pwshCloudCommandsCodePipelineRole: Type: AWS::IAM::Role Properties: RoleName: !Sub '${ServiceName}-CodePipelineRole' + Tags: + - Key: ServiceName + Value: !Ref ServiceName + - Key: StackName + Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType AssumeRolePolicyDocument: Version: '2012-10-17' Statement: @@ -599,8 +665,8 @@ Resources: Action: - s3:* Resource: - - !Sub 'arn:aws:s3:::${pwshCloudCommandsArtifactS3Bucket}' - - !Sub 'arn:aws:s3:::${pwshCloudCommandsArtifactS3Bucket}/*' + - !Sub 'arn:${AWS::Partition}:s3:::${pwshCloudCommandsArtifactS3Bucket}' + - !Sub 'arn:${AWS::Partition}:s3:::${pwshCloudCommandsArtifactS3Bucket}/*' - Effect: Allow Action: - iam:ListRoles @@ -613,10 +679,10 @@ Resources: - codebuild:StartBuild - codebuild:BatchGetBuilds Resource: - - !Sub arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/${UnitTestAndBuildProject} - - !Sub arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:build/${UnitTestAndBuildProject}:* - - !Sub arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/${IntegrationTestProject} - - !Sub arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:build/${IntegrationTestProject}:* + - !Sub arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:project/${UnitTestAndBuildProject} + - !Sub arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:build/${UnitTestAndBuildProject}:* + - !Sub arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:project/${IntegrationTestProject} + - !Sub arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:build/${IntegrationTestProject}:* - Effect: Allow Action: - kms:* @@ -633,10 +699,9 @@ Resources: Resource: !Ref CodeStarSourceConnection # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html - pwshCloudCommandsCloudFormationRole: + CloudFormationRole: Type: AWS::IAM::Role Properties: - RoleName: !Sub '${ServiceName}-CloudFormationRole' AssumeRolePolicyDocument: Version: '2012-10-17' Statement: @@ -660,6 +725,14 @@ Resources: Action: - '*' Resource: '*' + RoleName: !Sub '${ServiceName}-Pipeline-CloudFormationRole' + Tags: + - Key: ServiceName + Value: !Ref ServiceName + - Key: StackName + Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codepipeline-pipeline.html pwshCloudCommandsPipeline: @@ -675,6 +748,13 @@ Resources: Name: !Sub '${GitHubRepositoryName}-CodePipeline' RestartExecutionOnUpdate: false RoleArn: !GetAtt pwshCloudCommandsCodePipelineRole.Arn + Tags: + - Key: ServiceName + Value: !Ref ServiceName + - Key: StackName + Value: !Ref AWS::StackName + - Key: ResourceType + Value: !Ref ResourceType # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codepipeline-pipeline-stages.html # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codepipeline-pipeline-stages-actions.html # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codepipeline-pipeline-stages-actions-actiontypeid.html @@ -684,7 +764,7 @@ Resources: Stages: - Name: Source Actions: - - Name: Source + - Name: GitHubSource ActionTypeId: Version: '1' Owner: AWS @@ -693,59 +773,61 @@ Resources: Configuration: ConnectionArn: !Ref CodeStarSourceConnection FullRepositoryId: !Sub '${GitHubOwner}/${GitHubRepositoryName}' - BranchName: !Ref GitHubBranchName + BranchName: !Ref BranchName # InputArtifacts: # - InputArtifact # Namespace: String # OutputArtifactFormat: "CODE_ZIP" OutputArtifacts: - - Name: GitHubSourceCode + - Name: GitHubSource # Region: String # RoleArn: String RunOrder: 1 - Name: Build Actions: - Name: CodeBuild + InputArtifacts: + - Name: GitHubSource ActionTypeId: Category: Build Owner: AWS Version: '1' Provider: CodeBuild + OutputArtifacts: + - Name: CFNTemplateArtifact Configuration: ProjectName: Ref: UnitTestAndBuildProject - InputArtifacts: - - Name: GitHubSourceCode # Namespace: String - OutputArtifacts: - - Name: CFNTemplateArtifact # Region: String # RoleArn: String RunOrder: 1 - Name: Deploy Actions: - Name: DeployPrimaryControlPlane + InputArtifacts: + - Name: CFNTemplateArtifact ActionTypeId: Category: Deploy Owner: AWS Version: '1' Provider: CloudFormation + OutputArtifacts: + - Name: CreatedPrimaryControlPlaneStack Configuration: ActionMode: CREATE_UPDATE - RoleArn: !GetAtt pwshCloudCommandsCloudFormationRole.Arn + RoleArn: !GetAtt CloudFormationRole.Arn Capabilities: CAPABILITY_NAMED_IAM,CAPABILITY_AUTO_EXPAND StackName: !Ref ServiceName TemplateConfiguration: !Sub 'CFNTemplateArtifact::${PathToControlPlaneParametersJson}' TemplatePath: !Sub 'CFNTemplateArtifact::${PathToControlPlaneTemplate}' - InputArtifacts: - - Name: CFNTemplateArtifact # Namespace: String - OutputArtifacts: - - Name: CreatedPrimaryControlPlaneStack # Region: String RoleArn: !GetAtt pwshCloudCommandsCodePipelineRole.Arn RunOrder: 1 - Name: ValidateStack + InputArtifacts: + - Name: GitHubSource ActionTypeId: Category: Test Owner: AWS @@ -753,19 +835,12 @@ Resources: Provider: CodeBuild Configuration: ProjectName: !Ref IntegrationTestProject - InputArtifacts: - - Name: GitHubSourceCode # Namespace: String OutputArtifacts: - Name: ValidatedStack # Region: String # RoleArn: String RunOrder: 2 - Tags: - - Key: ServiceName - Value: !Ref ServiceName - - Key: StackName - Value: !Ref AWS::StackName Outputs: KMSKeyID: @@ -812,7 +887,7 @@ Outputs: pwshCloudCommandsCloudFormationRoleArn: Description: Arn of the pwshCloudCommandsCloudFormationRole IAM Role - Value: !GetAtt pwshCloudCommandsCloudFormationRole.Arn + Value: !GetAtt CloudFormationRole.Arn pwshCloudCommandsPipeline: Description: Pipeline Name diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md new file mode 100644 index 0000000..c374e24 --- /dev/null +++ b/docs/CHANGELOG.md @@ -0,0 +1,42 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.0.0] + +- Module Changes + - Updated module requirement for `Convert` from `0.6.0` to `1.5.0` + - Minor updates to `Invoke-XMLDataCheck` for code readability + - `Confirm-XMLDataSet` now evaluates `LastWriteTime` instead of `CreationTime` to determine cache freshness requirements + - `Find-CloudCommand` - updated help + - `Get-AllCloudCommandInfo` - updated help + - `Get-CloudCommandFromFile` - updated help +- Build Updates + - Updated all Github action files to: + - support ignore certain files for Readthedocs implementation + - updated actions from `v2` to `v3` + - Moved CHANGELOG from `.github` to `docs` + - `actions_bootstrap.ps1` - bumped module versions to latest + - All Infra/Infrastructure references changed to Integration + - Removed all test case uses of `Assert-MockCalled` + - Added additional unit tests for `Invoke-XMLDataCheck` + - AWS Deployment Updates + - Added Lambda function to metric age of data cache + - Updated CodeBuild Integration tests + - Changed alarm for cache data to reference correct SNS topic for alerts + - Added CloudWatch dashboard for data cache age metric + - Added support for readthedocs +- Misc + - Updated README to reference new badge urls for Github actions + - Updated `settings.json` for tab requirements to support Readthedocs + - Added `SECURITY.md` + - Updated `tasks.json` for cleaner references and additional tasks + - Updated `LICENSE` year + - Added metric dashboards to docs section + +## [0.8.0] + +- Initial release. diff --git a/docs/Find-CloudCommand.md b/docs/Find-CloudCommand.md index 5426bcf..ee5da99 100644 --- a/docs/Find-CloudCommand.md +++ b/docs/Find-CloudCommand.md @@ -8,7 +8,7 @@ schema: 2.0.0 # Find-CloudCommand ## SYNOPSIS -Finds PowerShell cloud command(s) that match the provided query. +Searches for PowerShell cloud commands matching a given query. ## SYNTAX @@ -17,22 +17,15 @@ Find-CloudCommand [-Query] [[-Filter] ] [-AllResults] [] [] ``` ## DESCRIPTION -Returns results from the entire PowerShell cloud command catalog. -It is recommended to use the Filter parameter to reduce the size of the result set. +This function provides comprehensive details on modules and functions from the entire catalog +of PowerShell cloud commands. +To manage the volume of data returned, it's advisable to use the +'Filter' parameter to focus on a specific cloud provider's commands. ## EXAMPLES @@ -27,19 +29,19 @@ It is recommended to use the Filter parameter to reduce the size of the result s Get-AllCloudCommandInfo -Filter AWS ``` -Returns module and function information of all known AWS PowerShell cloud commands. +Retrieves a complete list of modules and functions for AWS-specific PowerShell cloud commands. ### EXAMPLE 2 ``` Get-AllCloudCommandInfo ``` -Returns module and function information of all known PowerShell cloud commands. +Returns information on all available PowerShell cloud commands across various cloud platforms. ## PARAMETERS ### -Filter -Filter results to specific cloud platform (AWS/Azure/Oracle) +Filters the search to a specific cloud platform (AWS/Azure/Oracle). ```yaml Type: String diff --git a/docs/Get-CloudCommandFromFile.md b/docs/Get-CloudCommandFromFile.md index b452c1e..289916f 100644 --- a/docs/Get-CloudCommandFromFile.md +++ b/docs/Get-CloudCommandFromFile.md @@ -8,7 +8,7 @@ schema: 2.0.0 # Get-CloudCommandFromFile ## SYNOPSIS -Evaluates PowerShell files in specified path and identifies a list of PowerShell cloud functions and their associated modules. +Identifies PowerShell cloud functions and modules within files at a specified path. ## SYNTAX @@ -17,8 +17,9 @@ Get-CloudCommandFromFile [-Path] [] ``` ## DESCRIPTION -Discovers all PowerShell files in the specified path. -Parses each file and identifies all PowerShell cloud functions and their associated modules. +This function scans and analyzes PowerShell files in a given directory or path. +It parses each file to identify all PowerShell cloud functions and their associated modules, +providing a comprehensive overview of cloud-related commands used in the project. ## EXAMPLES @@ -28,7 +29,7 @@ $psCloud = Get-CloudCommandFromFile -Path "$env:HOME\pathToEvaluate" $psCloud ``` -Returns a list of PowerShell cloud functions and their associated modules found in files in the specified path. +Examines the specified path for PowerShell files, returning a list of cloud functions and their modules found in these files. ### EXAMPLE 2 ``` @@ -36,12 +37,12 @@ $psCloud = Get-CloudCommandFromFile -Path "$env:HOME\pathToEvaluate" $psCloud.CloudCommands.ModuleName | Select-Object -Unique ``` -Returns a list of unique module names found in use in files in the specified path. +After analyzing files at the specified path, this returns a list of unique module names utilized in those files. ## PARAMETERS ### -Path -File or Folder Path to evaluate. +File or directory path to be evaluated for cloud command usage. ```yaml Type: String diff --git a/media/diagrams/pwshCloudCommands_datapull.drawio b/docs/assets/diagrams/pwshCloudCommands_datapull.drawio similarity index 100% rename from media/diagrams/pwshCloudCommands_datapull.drawio rename to docs/assets/diagrams/pwshCloudCommands_datapull.drawio diff --git a/media/pwshCloudCommands_datapull.png b/docs/assets/pwshCloudCommands_datapull.png similarity index 100% rename from media/pwshCloudCommands_datapull.png rename to docs/assets/pwshCloudCommands_datapull.png diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..136908e --- /dev/null +++ b/docs/index.md @@ -0,0 +1,76 @@ +# pwshCloudCommands + +[![Minimum Supported PowerShell Version](https://img.shields.io/badge/PowerShell-5.1+-purple.svg)](https://github.com/PowerShell/PowerShell) [![PowerShell Gallery][psgallery-img]][psgallery-site] ![Cross Platform](https://img.shields.io/badge/platform-windows%20%7C%20macos%20%7C%20linux-lightgrey) [![License][license-badge]](LICENSE) [![Documentation Status](https://readthedocs.org/projects/pwshcloudcommands/badge/?version=latest)](https://pwshcloudcommands.readthedocs.io/en/latest/?badge=latest) + +[psgallery-img]: https://img.shields.io/powershellgallery/dt/pwshCloudCommands?label=Powershell%20Gallery&logo=powershell +[psgallery-site]: https://www.powershellgallery.com/packages/pwshCloudCommands +[license-badge]: https://img.shields.io/github/license/techthoughts2/pwshCloudCommands + +## What is pwshCloudCommands? + +pwshCloudCommands is a PowerShell module that simplifies the search and analysis of cloud-specific PowerShell commands, without the need to install cloud modules locally. It provides a dual discovery method: querying cloud commands across AWS, Azure, and Oracle, and scanning local project files to identify which cloud commands and modules are being utilized. + +## Why pwshCloudCommands? + +To aid in the discovery and analysis of cloud-specific PowerShell commands, pwshCloudCommands streamlines your workflow when working with PowerShell in the cloud. + +- **Find Cloud Commands Without Local Installs**: You can effortlessly search for any cloud command across AWS, Azure, and Oracle without installing the corresponding modules locally, reducing overhead and simplifying cloud command management. +- **Enjoy Advanced Search Capabilities**: Unlike the PowerShell Gallery, this module supports free-form searches. This is particularly useful when you're not sure of the exact command or syntax, offering an intuitive and flexible way to find what you need. +- **Benefit from Comprehensive Project Analysis**: The standout `Get-CloudCommandFromFile` function in `pwshCloudCommands` scans your project files to identify all necessary cloud modules. This feature is invaluable for creating dependency files or integrating into CI/CD processes, and it's extremely helpful for quickly understanding the cloud module requirements of new code or projects. + +## Getting Started + +### Installation + +```powershell +Install-Module -Name 'pwshCloudCommands' -Repository PSGallery -Scope CurrentUser +``` + +### Quick Start + +```powershell +#------------------------------------------------------------------------------------------------ +# import the pwshCloudCommands module +Import-Module -Name "pwshCloudCommands" +#------------------------------------------------------------------------------------------------ +# identify all PowerShell commands and modules used in the specified path +$psCloud = Get-CloudCommandFromFile -Path "$env:HOME\pathToEvaluate" +$psCloud +#------------------------------------------------------------------------------------------------ +# identify all unique modules used in the specified path - useful for CI/CD bootstrapping +$psCloud = Get-CloudCommandFromFile -Path "$env:HOME\pathToEvaluate" +$psCloud.CloudCommands.ModuleName | Select-Object -Unique +#------------------------------------------------------------------------------------------------ +# search for a specific cloud command on a specific cloud platform +Find-CloudCommand -Query Write-S3Object -Filter AWS +#------------------------------------------------------------------------------------------------ +# search for a specific cloud command on any cloud platform +Find-CloudCommand -Query New-OCIComputeInstance +#------------------------------------------------------------------------------------------------ +# wildcard search for a cloud command +Find-CloudCommand -Query New*VM* -Filter Azure +#------------------------------------------------------------------------------------------------ +# free-form search for a cloud command +$commands = Find-CloudCommand -Query 'I want to create a new compute instance in Oracle Cloud' +$commands +#------------------------------------------------------------------------------------------------ +# I want to get all cloud functions and modules that belong to a specific cloud platform +Get-AllCloudCommandInfo -Filter AWS +Get-AllCloudCommandInfo -Filter Azure +Get-AllCloudCommandInfo -Filter Oracle +#------------------------------------------------------------------------------------------------ +``` + +## How pwshCloudCommands Works + +pwshCloudCommands utilizes a cloud-based, event-driven workflow to generate a dynamic cache of known PowerShell cloud commands. This cache is periodically updated to ensure that it reflects the latest commands available from multiple cloud providers. You can view [cache metrics](pwshCloudCommand-Metrics.md) and read more about the [cache creation component](pwshCloudCommands_cache_workflow.md). + +## Features + +- Fully cross-platform and can be run on Windows, Linux, and macOS +- Module-Free Command Search: Discover PowerShell commands without the need for local module installations. + - Exact Function Name Search: Find specific functions, like Write-S3Object. + - Wildcard Search: Use patterns, such as New*VM*, to locate commands. + - Free-Form Search: Enter natural language queries like 'I want to create a new compute instance' for intuitive searching. +- Complete Cache Data Dump: Access a comprehensive dump containing all known PowerShell cloud commands for detailed analysis. +- Project File Analysis: Scan files and folders in your projects to identify used cloud functions and modules, crucial for project setup, discovery, and CI/CD pipeline integration. diff --git a/docs/pwshCloudCommands-FAQ.md b/docs/pwshCloudCommands-FAQ.md index feff6bf..a76c25a 100644 --- a/docs/pwshCloudCommands-FAQ.md +++ b/docs/pwshCloudCommands-FAQ.md @@ -4,8 +4,8 @@ ### Why would I use this vs Get-Command? -pwshCloudCommands is not a replacement for ```Get-Command```. The primary difference is that you do not have to have a module installed on your local device in order to use pwshCloudCommands. This enables you search for and identify PowerShell cloud commands across multiple cloud platforms without having to install any modules. This also enables you to scan directories and identify cloud commands used without necessarily having those modules on your local device. +While `Get-Command` is a powerful tool, pwshCloudCommands offers unique advantages for working with cloud-specific PowerShell commands. The key benefit is the ability to search for and identify cloud commands across multiple cloud platforms without the need to install their respective modules locally. Additionally, it allows you to scan directories and accurately detect the usage of cloud commands, regardless of whether those modules are present on your local system. ### How current is the PowerShell cloud command cache data? -Cloud changes frequently, and so do PowerShell cloud commands. The [Cache creation component](pwshCloudCommands_cache_workflow.md) ensures that the data cache is kept current. There is approximately a 1 week delay in the project cache data for all supported cloud platforms. +Given the rapid pace of change in cloud services, pwshCloudCommands is designed to keep up with the latest PowerShell cloud commands. The [cache](pwshCloudCommands_cache_workflow.md) is systematically updated to reflect the most recent commands, with a standard latency of about one week. diff --git a/docs/pwshCloudCommands-Metrics.md b/docs/pwshCloudCommands-Metrics.md new file mode 100644 index 0000000..05a41e6 --- /dev/null +++ b/docs/pwshCloudCommands-Metrics.md @@ -0,0 +1,10 @@ +# pwshCloudCommands Metrics + +## Metric Dashboards + +Up-to-date visualizations representing the age of the data cache and the frequency of download requests. + + diff --git a/docs/pwshCloudCommands.md b/docs/pwshCloudCommands.md index 3ae7d58..df49b78 100644 --- a/docs/pwshCloudCommands.md +++ b/docs/pwshCloudCommands.md @@ -2,7 +2,7 @@ Module Name: pwshCloudCommands Module Guid: be3705bf-2c38-413a-8973-9e409e826d35 Download Help Link: NA -Help Version: 0.8.0 +Help Version: 1.0.0 Locale: en-US --- @@ -12,12 +12,12 @@ Search, discover, and identify PowerShell cloud commands across multiple cloud p ## pwshCloudCommands Cmdlets ### [Find-CloudCommand](Find-CloudCommand.md) -Finds PowerShell cloud command(s) that match the provided query. +Searches for PowerShell cloud commands matching a given query. ### [Get-AllCloudCommandInfo](Get-AllCloudCommandInfo.md) -Returns module and function information for all known PowerShell cloud commands. +Returns detailed module and function information on all available PowerShell cloud commands. ### [Get-CloudCommandFromFile](Get-CloudCommandFromFile.md) -Evaluates PowerShell files in specified path and identifies a list of PowerShell cloud functions and their associated modules. +Identifies PowerShell cloud functions and modules within files at a specified path. diff --git a/docs/pwshCloudCommands_cache_workflow.md b/docs/pwshCloudCommands_cache_workflow.md index f80971b..0ee7109 100644 --- a/docs/pwshCloudCommands_cache_workflow.md +++ b/docs/pwshCloudCommands_cache_workflow.md @@ -8,8 +8,8 @@ This workflow continuously updates the known cache of PowerShell Cloud commands ## Deployment Stack -* [Cloudformation for cache deployment](../cloudformation) +* [CloudFormation for cache deployment](https://github.com/techthoughts2/pwshCloudCommands/tree/main/cloudformation) ## Design Diagram -![pwshCloudCommands PowerShell Cloud Commands data cache creation](../media/pwshCloudCommands_datapull.png) +![pwshCloudCommands PowerShell Cloud Commands data cache creation](assets/pwshCloudCommands_datapull.png) diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..d1f2c7f --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,7 @@ +# https://github.com/readthedocs-examples/example-mkdocs-basic/blob/main/docs/requirements.txt +# requirements.txt +jinja2==3.0.3 +mkdocs>=1.4.2 +mkdocs-material>=9.0.12 #https://github.com/squidfunk/mkdocs-material +pygments>=2.14.0 +# mdx_truly_sane_lists diff --git a/lambdafunctions/PowerShell/pwshCCPubXMLMonitor/pwshCCPubXMLMonitor.build.ps1 b/lambdafunctions/PowerShell/pwshCCPubXMLMonitor/pwshCCPubXMLMonitor.build.ps1 new file mode 100644 index 0000000..e4e661f --- /dev/null +++ b/lambdafunctions/PowerShell/pwshCCPubXMLMonitor/pwshCCPubXMLMonitor.build.ps1 @@ -0,0 +1,165 @@ +<# + .SYNOPSIS + An Invoke-Build Build file for an AWS PowerShell Lambda Function + + .DESCRIPTION + This build file is configured for AWS CodeBuild builds, but will work locally as well. + + Build steps can include: + - InstallDependencies + - Clean + - Analyze + - Test + - Build + - Archive + + The default build will not call the 'InstallDependencies' task, but can be used if you want PSDepend + to install pre-requisite modules. "Invoke-Build -Task InstallDependencies" + + This build will pull in configurations from the ".Settings.ps1" file as well, where users can + more easily customize the build process if required. + + .EXAMPLE + Invoke-Build + + This will perform the default build tasks: Clean, Analyze, Test, Build, Archive + + .EXAMPLE + Invoke-Build -Task Analyze,Test + + This will perform only the Analyze and Test tasks. +#> + +# Include: Settings +$ScriptName = (Split-Path -Path $BuildFile -Leaf).Split('.')[0] +. "./$ScriptName.settings.ps1" + +# Default Build +task . Clean, ImportModules, Analyze, Build, Publish + +# Pre-build variables to configure +Enter-Build { + $script:LambdaName = (Split-Path -Path $BuildFile -Leaf).Split('.')[0] + + # Identify other required paths + $script:LambdaSourcePath = $BuildRoot + $script:LambdaScriptPath = Join-Path -Path $script:LambdaSourcePath -ChildPath "$ScriptName.ps1" + $script:ArtifactsPath = Join-Path -Path $BuildRoot -ChildPath 'Artifacts' + $script:ArtifactPackage = Join-Path -Path $script:ArtifactsPath -ChildPath "$ScriptName.zip" + $script:PowerShellLambdaPath = Split-Path -Path $script:LambdaSourcePath + $script:StagingPath = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath 'LambdaStaging' + + if ([String]::IsNullOrWhiteSpace($env:CODEBUILD_SRC_DIR)) { + $script:LambdaFunctionsPath = Split-Path -Path $script:PowerShellLambdaPath + $script:CodeBuildRoot = Split-Path -Path $script:LambdaFunctionsPath + } + else { + $script:CodeBuildRoot = $env:CODEBUILD_SRC_DIR + } + $script:ModulesRoot = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath 'Modules' + $script:CFNParameterFilePath = Join-Path -Path $script:CodeBuildRoot -ChildPath 'cloudformation' + + if (-not(Test-Path -Path $script:CFNParameterFilePath)) { + throw ('Unable to find the cloudformation Path: {0}' -f $script:CFNParameterFilePath) + } +} + +# Synopsis: Imports PowerShell Modules +task ImportModules { + Write-Host 'Importing PowerShell Modules' + + $manifests = Get-ChildItem -Path $script:ModulesRoot -Recurse -Filter "*.psd1" + foreach ($manifest in $manifests) { + if (Get-Module -Name $manifest.BaseName) { + Remove-Module -Name $manifest.BaseName + } + + Write-Host ' -' $manifest.BaseName + Import-Module $manifest.FullName -Force -Verbose:$false + } +} + +# Synopsis: Clean Artifacts Directory +task Clean { + foreach ($path in $script:ArtifactsPath, $script:StagingPath) { + if (Test-Path -Path $path) { + $null = Remove-Item -Path $path -Recurse -Force + } + + $null = New-Item -ItemType Directory -Path $path -Force + } +} + +# Synopsis: Invokes Script Analyzer against the Module source path +task Analyze { + $scriptAnalyzerParams = @{ + Path = $script:LambdaScriptPath + Severity = @('Error', 'Warning') + Recurse = $true + ExcludeRule = @('PSAvoidUsingWriteHost', 'PSUseShouldProcessForStateChangingFunctions') + Verbose = $false + } + + $scriptAnalyzerResults = Invoke-ScriptAnalyzer @scriptAnalyzerParams + + if ($scriptAnalyzerResults) { + $scriptAnalyzerResults | Format-Table + throw 'One or more PSScriptAnalyzer errors/warnings where found.' + } +} + +# Synopsis: Builds the Module to the Artifacts folder +task Build { + Write-Verbose -Message 'Compiling the AWS Lambda Package' + $script:LambdaPackage = New-AWSPowerShellLambdaPackage -ScriptPath $script:LambdaScriptPath -StagingDirectory $script:StagingPath -OutputPackage $script:ArtifactPackage -Verbose + Write-Host 'AWS Lambda Function Handler:' $script:LambdaPackage.LambdaHandler + Write-Host 'PowerShell Function Handler Environment Variable Name:' $script:LambdaPackage.PowerShellFunctionHandlerEnvVar +} + +task Publish { + if ([String]::IsNullOrWhiteSpace($env:CODEBUILD_SRC_DIR) -and [String]::IsNullOrWhiteSpace($env:CODEBUILD_RESOLVED_SOURCE_VERSION)) { + Write-Warning -Message 'Not publishing the artifact because the code is not running inside a CodeBuild Project' + } + else { + 'Publishing Lambda Function to S3' + + $s3Key = '{0}/{1}/lambdafunctions/PowerShell/{2}.zip' -f $env:S3_KEY_PREFIX, $env:CODEBUILD_RESOLVED_SOURCE_VERSION, $ScriptName + ' - S3Key:/{0}/{1}' -f $env:ARTIFACT_S3_BUCKET, $s3Key + + Write-S3Object -BucketName $env:ARTIFACT_S3_BUCKET -Key $s3Key -File $script:ArtifactPackage + + # Update json parameter files + $cfnLambdaS3KeyParameterName = 'LMFunctionS3Key{0}' -f $ScriptName + Write-Verbose -Message "JSON Parameter Name for cloudformation S3 Key: $cfnLambdaS3KeyParameterName" -Verbose + + $cfnLambdaHandlerParameterName = 'LMFunctionHandler{0}' -f $ScriptName + Write-Verbose -Message "JSON Parameter Name for Lambda Function Handler: $cfnLambdaHandlerParameterName" -Verbose + + $jsonFiles = Get-ChildItem -Path $script:CFNParameterFilePath -Recurse -Filter "*.json" + foreach ($jsonFile in $jsonFiles) { + 'Processing {0}' -f $jsonFile.Name + $jsonData = Get-Content -Path $jsonFile.FullName -Raw | ConvertFrom-Json + + # Update cfnLambdaS3KeyParameterName in json parameters + try { + $jsonData.Parameters.$cfnLambdaS3KeyParameterName = $s3Key + ' - Updated the json parameter "{0}" with "{1}".' -f $cfnLambdaS3KeyParameterName, $s3Key + } + catch { + ' - Unable to find the json parameter "{0}". No modifications being made.' -f $cfnLambdaS3KeyParameterName + } + + # Update cfnLambdaHandlerParameterName in json parameters + try { + $jsonData.Parameters.$cfnLambdaHandlerParameterName = $script:LambdaPackage.LambdaHandler + ' - Updated the json parameter "{0}" with "{1}".' -f $cfnLambdaHandlerParameterName, $script:LambdaPackage.LambdaHandler + } + catch { + ' - Unable to find the json parameter "{0}". No modifications being made.' -f $cfnLambdaHandlerParameterName + } + + # Export the json back to disk + $jsonData | ConvertTo-Json | Out-File -FilePath $jsonFile.FullName -Force -Encoding utf8 + } + } +} diff --git a/lambdafunctions/PowerShell/pwshCCPubXMLMonitor/pwshCCPubXMLMonitor.ps1 b/lambdafunctions/PowerShell/pwshCCPubXMLMonitor/pwshCCPubXMLMonitor.ps1 new file mode 100644 index 0000000..38f219a --- /dev/null +++ b/lambdafunctions/PowerShell/pwshCCPubXMLMonitor/pwshCCPubXMLMonitor.ps1 @@ -0,0 +1,137 @@ +# PowerShell script file to be executed as an AWS Lambda function. +# +# When executing in Lambda the following variables will be predefined. +# $LambdaInput - A PSObject that contains the Lambda function input data. +# $LambdaContext - An Amazon.Lambda.Core.ILambdaContext object that contains information about the currently running Lambda environment. +# +# The last item in the PowerShell pipeline will be returned as the result of the Lambda function. +# +# To include PowerShell modules with your Lambda function, like the AWS.Tools.Common module, add a "#Requires" statement +# indicating the module and version. + +# Env variables that are set by the AWS Lambda environment: +# $env:S3_BUCKET_NAME +# $env:TELEGRAM_SECRET +# $env:SERVICE_NAME + +#Requires -Modules @{ModuleName='AWS.Tools.Common';ModuleVersion='4.1.472'} +#Requires -Modules @{ModuleName='AWS.Tools.CloudWatch';ModuleVersion='4.1.472'} +#Requires -Modules @{ModuleName='AWS.Tools.SimpleSystemsManagement';ModuleVersion='4.1.472'} +#Requires -Modules @{ModuleName='AWS.Tools.S3';ModuleVersion='4.1.472'} +#Requires -Modules @{ModuleName='PoshGram';ModuleVersion='2.3.0'} + +# Uncomment to send the input event to CloudWatch Logs +Write-Host (ConvertTo-Json -InputObject $LambdaInput -Compress -Depth 5) + +# CW Event Scheduled -> Lambda -> CW Metric + +#region supportingFunctions + +function Send-TelegramMessage { + <# + .SYNOPSIS + Sends message to Telegram for notification. + #> + param ( + [Parameter(Mandatory = $true, + HelpMessage = 'Message to send to telegram')] + [string] + $Message + ) + + if ($null -eq $script:telegramToken -or $null -eq $script:telegramChannel) { + try { + $getSSMParameterValueSplatToken = @{ + Name = 'telegramtoken' + WithDecryption = $true + ErrorAction = 'Stop' + } + $getSSMParameterValueSplatChannel = @{ + Name = 'telegramchannel' + WithDecryption = $true + ErrorAction = 'Stop' + } + $script:telegramToken = Get-SSMParameterValue @getSSMParameterValueSplatToken + $script:telegramChannel = Get-SSMParameterValue @getSSMParameterValueSplatChannel + } + catch { + throw $_ + } + } #if_token_channel_null + + if ([string]::IsNullOrWhiteSpace($script:telegramToken) -or [string]::IsNullOrWhiteSpace($script:telegramChannel)) { + throw 'Parameters not successfully retrieved' + } + else { + Write-Host 'Parameters retrieved.' + $token = $script:telegramToken.Parameters.Value + $channel = $script:telegramChannel.Parameters.Value + $out = Send-TelegramTextMessage -BotToken $token -ChatID $channel -Message $Message + Write-Host ($out | Out-String) + } +} #Send-TelegramMessage + +#endregion + +$key = '{0}.zip' -f $env:SERVICE_NAME +Write-Host ('Retrieving {0} from {1}..' -f $key, $env:S3_BUCKET_NAME) +try { + $getS3ObjectSplat = @{ + BucketName = $env:S3_BUCKET_NAME + Key = $key + ErrorAction = 'Stop' + } + $objInfo = Get-S3Object @getS3ObjectSplat +} +catch { + Write-Warning -Message 'Error retrieving object from S3' + Write-Error $_ + Send-TelegramMessage -Message '\\\ Project pwshCloudCommands - PubXMLMonitor Error retrieving object from S3' + return +} + +if ($null -eq $objInfo) { + Write-Warning -Message 'No object returned from S3' + Send-TelegramMessage -Message '\\\ Project pwshCloudCommands - PubXMLMonitor The S3 object was not found' +} + +Write-Host 'Getting current date' +$now = Get-Date + +Write-Host 'Determining how old the object is' +$diff = $now - $objInfo.LastModified +$diffDays = $diff.Days +Write-Host ('Object is {0} days old' -f $diffDays) + +# Create a MetricDatum .NET object +$MetricDatum = [Amazon.CloudWatch.Model.MetricDatum]::new() +$MetricDatum.MetricName = 'PubXMLAge' +$MetricDatum.Value = $diffDays + +# Create a Dimension .NET object +$Dimension = [Amazon.CloudWatch.Model.Dimension]::new() +$Dimension.Name = 'PubXML' +$Dimension.Value = 'DaysOld' + +# Assign the Dimension object to the MetricDatum's Dimensions property +$MetricDatum.Dimensions = $Dimension + +$Namespace = 'pwshCloudCommands' + +try { + + # Write the metric data to the CloudWatch service + $writeCWMetricDataSplat = @{ + Namespace = $Namespace + MetricData = $MetricDatum + ErrorAction = 'Stop' + } + Write-CWMetricData @writeCWMetricDataSplat +} +catch { + $errorMessage = $_.Exception.Message + Write-Error -Message ('Something went wrong: {0}' -f $errorMessage) + Send-TelegramMessage -Message '\\\ Project pwshCloudCommands - PubXMLMonitor Error sending metric data to CloudWatch' +} + +return $true diff --git a/lambdafunctions/PowerShell/pwshCCPubXMLMonitor/pwshCCPubXMLMonitor.settings.ps1 b/lambdafunctions/PowerShell/pwshCCPubXMLMonitor/pwshCCPubXMLMonitor.settings.ps1 new file mode 100644 index 0000000..87a0c2f --- /dev/null +++ b/lambdafunctions/PowerShell/pwshCCPubXMLMonitor/pwshCCPubXMLMonitor.settings.ps1 @@ -0,0 +1,54 @@ +<# + .SYNOPSIS + Use this for custom modifications to the build process if needed. +#> + +############################################################################### +# Before/After Hooks for the Core Task: Clean +############################################################################### + +# Synopsis: Executes before the Clean task. +#task BeforeClean -Before Clean {} + +# Synopsis: Executes after the Clean task. +#task AfterClean -After Clean {} + +############################################################################### +# Before/After Hooks for the Core Task: Analyze +############################################################################### + +# Synopsis: Executes before the Analyze task. +#task BeforeAnalyze -Before Analyze {} + +# Synopsis: Executes after the Analyze task. +#task AfterAnalyze -After Analyze {} + +############################################################################### +# Before/After Hooks for the Core Task: Archive +############################################################################### + +# Synopsis: Executes before the Archive task. +#task BeforeArchive -Before Archive {} + +# Synopsis: Executes after the Archive task. +#task AfterArchive -After Archive {} + +############################################################################### +# Before/After Hooks for the Core Task: Build +############################################################################### + +# Synopsis: Executes before the Build task. +#task BeforeBuild -Before Build {} + +# Synopsis: Executes after the Build task. +#task AfterBuild -After Build {} + +############################################################################### +# Before/After Hooks for the Core Task: Test +############################################################################### + +# Synopsis: Executes before the Test Task. +#task BeforeTest -Before Test {} + +# Synopsis: Executes after the Test Task. +#task AfterTest -After Test {} diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..0275f33 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,85 @@ +# https://www.mkdocs.org/user-guide/configuration/ +# https://www.mkdocs.org/user-guide/writing-your-docs/ +# https://www.mkdocs.org/user-guide/writing-your-docs/#writing-with-markdown +# https://mkdocs.readthedocs.io/en/0.15.2/user-guide/writing-your-docs/ +# https://mkdocs.readthedocs.io/en/0.15.2/user-guide/styling-your-docs/ +# https://example-mkdocs-basic.readthedocs.io/en/latest/ +# https://github.com/mkdocs/mkdocs/blob/master/mkdocs.yml +# https://squidfunk.github.io/mkdocs-material/creating-your-site/ +# mkdocs.yml + +site_name: pwshCloudCommands +# site_url: +repo_url: https://github.com/techthoughts2/pwshCloudCommands +# repo_name: +# edit_uri: edit/main/docs/ +# edit_uri_template: +site_description: Search, discover, and identify PowerShell cloud commands across multiple cloud providers. # meta tag to the generated HTML header +site_author: Jake Morrison # meta tag to the generated HTML header +copyright: "pwshCloudCommands is licensed under the MIT license" +# remote_branch: +# remote_name: +# docs_dir: docs +# site_dir: +# extra_css: +# extra_javascript: +markdown_extensions: + # Python Markdown + - admonition + - toc: + permalink: true + # code highlighting + - pymdownx.highlight: + use_pygments: true + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences + +# extra_templates: +# extra: +theme: + name: material + language: en + # custom_dir: overrides + features: + # - navigation.tabs + # - navigation.tabs.sticky + # - navigation.path + # favicon: + # icon: + # repo: + # font: + # text: Work Sans + # logo: + # palette: + # primary: teal + # palette: + # # Palette toggle for light mode + # - media: "(prefers-color-scheme: light)" + # scheme: default + # primary: light blue + # accent: pink + # toggle: + # icon: material/brightness-7 + # name: Switch to dark mode + + # # Palette toggle for dark mode + # - media: "(prefers-color-scheme: dark)" + # scheme: slate + # primary: indigo + # accent: pink + # toggle: + # icon: material/brightness-4 + # name: Switch to light mode +nav: + - Home: index.md + - Functions: + - Find-CloudCommand: Find-CloudCommand.md + - Get-AllCloudCommandInfo: Get-AllCloudCommandInfo.md + - Get-CloudCommandFromFile: Get-CloudCommandFromFile.md + - Metrics: pwshCloudCommands-Metrics.md + - FAQ: pwshCloudCommands-FAQ.md + - Cache Design: pwshCloudCommands_cache_workflow.md + - Change Log: CHANGELOG.md diff --git a/src/Tests/Infrastructure/pwshCloudCommands.Infra.Tests.ps1 b/src/Tests/Integration/pwshCloudCommands.Infra.Tests.ps1 similarity index 99% rename from src/Tests/Infrastructure/pwshCloudCommands.Infra.Tests.ps1 rename to src/Tests/Integration/pwshCloudCommands.Infra.Tests.ps1 index d20a657..7820f77 100644 --- a/src/Tests/Infrastructure/pwshCloudCommands.Infra.Tests.ps1 +++ b/src/Tests/Integration/pwshCloudCommands.Infra.Tests.ps1 @@ -18,6 +18,7 @@ InModuleScope 'pwshCloudCommands' { $PathToAssets = [System.IO.Path]::Combine('..', 'asset') } #beforeAll Context 'Find-CloudCommand' { + It 'should return expected results for a function query' { $eval = Find-CloudCommand -Query Write-S3Object -Filter AWS $eval.Name | Should -BeExactly 'Write-S3Object' @@ -58,4 +59,4 @@ InModuleScope 'pwshCloudCommands' { } #context_Get-CloudCommandFromFile } #describe -} #inModule \ No newline at end of file +} #inModule diff --git a/src/Tests/Unit/Private/Confirm-XMLDataSet.Tests.ps1 b/src/Tests/Unit/Private/Confirm-XMLDataSet.Tests.ps1 index 1adb431..a89ea1f 100644 --- a/src/Tests/Unit/Private/Confirm-XMLDataSet.Tests.ps1 +++ b/src/Tests/Unit/Private/Confirm-XMLDataSet.Tests.ps1 @@ -30,6 +30,7 @@ InModuleScope 'pwshCloudCommands' { CreationTime = [datetime]'01/06/20 21:17:21' CreationTimeUtc = [datetime]'01/07/20 05:17:21' LastAccessTime = [datetime]'01/06/20 21:17:22' + LastWriteTime = [datetime]'01/06/20 21:17:21' } } #endMock Mock -CommandName Get-Date -MockWith { @@ -84,6 +85,7 @@ InModuleScope 'pwshCloudCommands' { CreationTime = [datetime]'01/06/20 21:17:21' CreationTimeUtc = [datetime]'01/07/20 05:17:21' LastAccessTime = [datetime]'01/06/20 21:17:22' + LastWriteTime = [datetime]'01/06/20 21:17:21' } return $obj } diff --git a/src/Tests/Unit/Private/Get-CloudCommandFromToken.Tests.ps1 b/src/Tests/Unit/Private/Get-CloudCommandFromToken.Tests.ps1 index 4627f58..33bce32 100644 --- a/src/Tests/Unit/Private/Get-CloudCommandFromToken.Tests.ps1 +++ b/src/Tests/Unit/Private/Get-CloudCommandFromToken.Tests.ps1 @@ -421,7 +421,7 @@ InModuleScope 'pwshCloudCommands' { It 'should run the commands the expected number of times' { Get-CloudCommandFromToken -Tokens $tokens - Assert-MockCalled -CommandName Search-XMLDataSet -Times 12 -Scope It + Should -Invoke -CommandName Search-XMLDataSet -Times 12 -Scope It } #it It 'should return null if no results are found' { diff --git a/src/Tests/Unit/Private/Invoke-XMLDataCheck.Tests.ps1 b/src/Tests/Unit/Private/Invoke-XMLDataCheck.Tests.ps1 index beada49..22b9c43 100644 --- a/src/Tests/Unit/Private/Invoke-XMLDataCheck.Tests.ps1 +++ b/src/Tests/Unit/Private/Invoke-XMLDataCheck.Tests.ps1 @@ -35,12 +35,12 @@ InModuleScope 'pwshCloudCommands' { It 'Should process by default' { Invoke-XMLDataCheck - Assert-MockCalled Invoke-XMLDataCheck -Scope It -Exactly -Times 1 + Should -Invoke -CommandName Invoke-XMLDataCheck -Scope It -Exactly -Times 1 } #it It 'Should not process on explicit request for confirmation (-Confirm)' { { Invoke-XMLDataCheck -Confirm } - Assert-MockCalled Invoke-XMLDataCheck -Scope It -Exactly -Times 0 + Should -Invoke -CommandName Invoke-XMLDataCheck -Scope It -Exactly -Times 0 } #it It 'Should not process on implicit request for confirmation (ConfirmPreference)' { @@ -48,12 +48,12 @@ InModuleScope 'pwshCloudCommands' { $ConfirmPreference = 'Low' Invoke-XMLDataCheck } - Assert-MockCalled Invoke-XMLDataCheck -Scope It -Exactly -Times 0 + Should -Invoke -CommandName Invoke-XMLDataCheck -Scope It -Exactly -Times 0 } #it It 'Should not process on explicit request for validation (-WhatIf)' { { Invoke-XMLDataCheck -WhatIf } - Assert-MockCalled Invoke-XMLDataCheck -Scope It -Exactly -Times 0 + Should -Invoke -CommandName Invoke-XMLDataCheck -Scope It -Exactly -Times 0 } #it It 'Should not process on implicit request for validation (WhatIfPreference)' { @@ -61,16 +61,16 @@ InModuleScope 'pwshCloudCommands' { $WhatIfPreference = $true Invoke-XMLDataCheck } - Assert-MockCalled Invoke-XMLDataCheck -Scope It -Exactly -Times 0 + Should -Invoke -CommandName Invoke-XMLDataCheck -Scope It -Exactly -Times 0 } #it It 'Should process on force' { $ConfirmPreference = 'Medium' Invoke-XMLDataCheck -Force - Assert-MockCalled Invoke-XMLDataCheck -Scope It -Exactly -Times 1 + Should -Invoke -CommandName Invoke-XMLDataCheck -Scope It -Exactly -Times 1 } #it - } #context_shouldprocess + } #context_ShouldProcess BeforeEach { Mock -CommandName Confirm-DataLocation -MockWith { $true @@ -125,6 +125,89 @@ InModuleScope 'pwshCloudCommands' { Invoke-XMLDataCheck -Force | Should -BeExactly $true } #it + It 'should not run commands if the data file is not confirmed' { + Mock -CommandName Confirm-DataLocation -MockWith { + $false + } #endMock + Mock -CommandName Confirm-XMLDataSet -MockWith { + $false + } #endMock + Mock -CommandName Get-XMLDataSet -MockWith { + $false + } #endMock + Mock -CommandName Expand-XMLDataSet -MockWith { + $false + } #endMock + Invoke-XMLDataCheck -Force + Should -Invoke -CommandName Confirm-XMLDataSet -Scope It -Exactly -Times 0 + Should -Invoke -CommandName Get-XMLDataSet -Scope It -Exactly -Times 0 + Should -Invoke -CommandName Expand-XMLDataSet -Scope It -Exactly -Times 0 + } #it + + It 'should run Confirm-XMLDataSet if the data location is confirmed' { + Mock -CommandName Confirm-DataLocation -MockWith { + $true + } #endMock + Invoke-XMLDataCheck -Force + Should -Invoke -CommandName Confirm-XMLDataSet -Scope It -Exactly -Times 1 + } #it + + It 'should not run Get-XMLDataSet if the data set is confirmed' { + Mock -CommandName Confirm-DataLocation -MockWith { + $true + } #endMock + Mock -CommandName Confirm-XMLDataSet -MockWith { + $true + } #endMock + Invoke-XMLDataCheck -Force + Should -Invoke -CommandName Confirm-XMLDataSet -Scope It -Exactly -Times 1 + Should -Invoke -CommandName Get-XMLDataSet -Scope It -Exactly -Times 0 + } #it + + It 'should run Get-XMLDataSet if the data set is not confirmed' { + Mock -CommandName Confirm-DataLocation -MockWith { + $true + } #endMock + Mock -CommandName Confirm-XMLDataSet -MockWith { + $false + } #endMock + Invoke-XMLDataCheck -Force + Should -Invoke -CommandName Confirm-XMLDataSet -Scope It -Exactly -Times 1 + Should -Invoke -CommandName Get-XMLDataSet -Scope It -Exactly -Times 1 + } #it + + It 'should not run Expand-XMLDataSet if the data can not be retrieved' { + Mock -CommandName Confirm-DataLocation -MockWith { + $true + } #endMock + Mock -CommandName Confirm-XMLDataSet -MockWith { + $false + } #endMock + Mock -CommandName Get-XMLDataSet -MockWith { + $false + } #endMock + Invoke-XMLDataCheck -Force + Should -Invoke -CommandName Confirm-XMLDataSet -Scope It -Exactly -Times 1 + Should -Invoke -CommandName Get-XMLDataSet -Scope It -Exactly -Times 1 + Should -Invoke -CommandName Expand-XMLDataSet -Scope It -Exactly -Times 0 + } #it + + It 'should run Expand-XMLDataSet if the data can be retrieved' { + Mock -CommandName Confirm-DataLocation -MockWith { + $true + } #endMock + Mock -CommandName Confirm-XMLDataSet -MockWith { + $false + } #endMock + Mock -CommandName Get-XMLDataSet -MockWith { + $true + } #endMock + Invoke-XMLDataCheck -Force + Should -Invoke -CommandName Confirm-XMLDataSet -Scope It -Exactly -Times 1 + Should -Invoke -CommandName Get-XMLDataSet -Scope It -Exactly -Times 1 + Should -Invoke -CommandName Expand-XMLDataSet -Scope It -Exactly -Times 1 + } #it + } #context_Success } #describe_Invoke-XMLDataCheck } #inModule diff --git a/src/pwshCloudCommands.build.ps1 b/src/pwshCloudCommands.build.ps1 index 56a4bdf..704e495 100644 --- a/src/pwshCloudCommands.build.ps1 +++ b/src/pwshCloudCommands.build.ps1 @@ -12,7 +12,7 @@ - DevCC - CreateHelpStart - Build - - InfraTest + - IntegrationTest - Archive .EXAMPLE Invoke-Build @@ -23,7 +23,7 @@ This will perform only the Analyze and Test Add-BuildTasks. .NOTES - This build will pull in configurations from the ".Settings.ps1" file as well, where users can more easily customize the build process if required. + This build file by Catesta will pull in configurations from the ".Settings.ps1" file as well, where users can more easily customize the build process if required. https://github.com/nightroman/Invoke-Build https://github.com/nightroman/Invoke-Build/wiki/Build-Scripts-Guidelines If using VSCode you can use the generated tasks.json to execute the various tasks in this build file. @@ -53,7 +53,7 @@ $str += 'Analyze', 'Test' $str += 'CreateHelpStart' $str2 = $str $str2 += 'Build', 'Archive' -$str += 'Build', 'InfraTest', 'Archive' +$str += 'Build', 'IntegrationTest', 'Archive' Add-BuildTask -Name . -Jobs $str #Local testing build process @@ -62,8 +62,8 @@ Add-BuildTask TestLocal Clean, ImportModuleManifest, Analyze, Test #Local help file creation process Add-BuildTask HelpLocal Clean, ImportModuleManifest, CreateHelpStart -#Full build sans infra tests -Add-BuildTask BuildNoInfra -Jobs $str2 +#Full build sans integration tests +Add-BuildTask BuildNoIntegration -Jobs $str2 # Pre-build variables to be used by other portions of the script Enter-Build { @@ -82,7 +82,7 @@ Enter-Build { $script:TestsPath = Join-Path -Path $BuildRoot -ChildPath 'Tests' $script:UnitTestsPath = Join-Path -Path $script:TestsPath -ChildPath 'Unit' - $script:InfraTestsPath = Join-Path -Path $script:TestsPath -ChildPath 'Infrastructure' + $script:IntegrationTestsPath = Join-Path -Path $script:TestsPath -ChildPath 'Integration' $script:ArtifactsPath = Join-Path -Path $BuildRoot -ChildPath 'Artifacts' $script:ArchivePath = Join-Path -Path $BuildRoot -ChildPath 'Archive' @@ -92,9 +92,9 @@ Enter-Build { # Ensure our builds fail until if below a minimum defined code test coverage threshold $script:coverageThreshold = 95 - [version]$script:MinPesterVersion = '5.2.2' [version]$script:MaxPesterVersion = '5.99.99' + $script:testOutputFormat = 'NUnitXML' } #Enter-Build # Define headers as separator, task path, synopsis, and location, e.g. for Ctrl+Click in VSCode. @@ -133,7 +133,7 @@ Add-BuildTask TestModuleManifest -Before ImportModuleManifest { Assert-Build (Test-Path $script:ModuleManifestFile) 'Unable to locate the module manifest file.' Assert-Build (Test-ManifestBool -Path $script:ModuleManifestFile) 'Module Manifest test did not pass verification.' Write-Build Green ' ...Module Manifest Verification Complete!' -} +} #f5b33218-bde4-4028-b2a1-9c206f089503 # Synopsis: Load the module project Add-BuildTask ImportModuleManifest { @@ -185,7 +185,6 @@ Add-BuildTask Analyze { Add-BuildTask AnalyzeTests -After Analyze { if (Test-Path -Path $script:TestsPath) { - $scriptAnalyzerParams = @{ Path = $script:TestsPath Setting = 'PSScriptAnalyzerSettings.psd1' @@ -247,8 +246,7 @@ Add-BuildTask Test { New-Item -Path $testOutPutPath -ItemType Directory | Out-Null } if (Test-Path -Path $script:UnitTestsPath) { - - $pesterConfiguration = [PesterConfiguration]::new() + $pesterConfiguration = New-PesterConfiguration $pesterConfiguration.run.Path = $script:UnitTestsPath $pesterConfiguration.Run.PassThru = $true $pesterConfiguration.Run.Exit = $false @@ -259,11 +257,11 @@ Add-BuildTask Test { $pesterConfiguration.CodeCoverage.OutputFormat = 'JaCoCo' $pesterConfiguration.TestResult.Enabled = $true $pesterConfiguration.TestResult.OutputPath = "$testOutPutPath\PesterTests.xml" - $pesterConfiguration.TestResult.OutputFormat = 'NUnitXml' + $pesterConfiguration.TestResult.OutputFormat = $script:testOutputFormat $pesterConfiguration.Output.Verbosity = 'Detailed' Write-Build White ' Performing Pester Unit Tests...' - # Publish Test Results as NUnitXml + # Publish Test Results $testResults = Invoke-Pester -Configuration $pesterConfiguration # This will output a nice json for each failed test (if running in CodeBuild) @@ -278,7 +276,6 @@ Add-BuildTask Test { $numberFails = $testResults.FailedCount Assert-Build($numberFails -eq 0) ('Failed "{0}" unit tests.' -f $numberFails) - Write-Build Gray (' ...CODE COVERAGE - CommandsExecutedCount: {0}' -f $testResults.CodeCoverage.CommandsExecutedCount) Write-Build Gray (' ...CODE COVERAGE - CommandsAnalyzedCount: {0}' -f $testResults.CodeCoverage.CommandsAnalyzedCount) @@ -313,8 +310,7 @@ Add-BuildTask DevCC { Write-Build White " Importing desired Pester version. Min: $script:MinPesterVersion Max: $script:MaxPesterVersion" Remove-Module -Name Pester -Force -ErrorAction SilentlyContinue # there are instances where some containers have Pester already in the session Import-Module -Name Pester -MinimumVersion $script:MinPesterVersion -MaximumVersion $script:MaxPesterVersion -ErrorAction 'Stop' - - $pesterConfiguration = [PesterConfiguration]::new() + $pesterConfiguration = New-PesterConfiguration $pesterConfiguration.run.Path = $script:UnitTestsPath $pesterConfiguration.CodeCoverage.Enabled = $true $pesterConfiguration.CodeCoverage.Path = "$PSScriptRoot\$ModuleName\*\*.ps1" @@ -496,18 +492,17 @@ Add-BuildTask Build { Write-Build Green ' ...Build Complete!' } #Build -#Synopsis: Invokes all Pester Infrastructure Tests in the Tests\Infrastructure folder (if it exists) -Add-BuildTask InfraTest { - if (Test-Path -Path $script:InfraTestsPath) { +#Synopsis: Invokes all Pester Integration Tests in the Tests\Integration folder (if it exists) +Add-BuildTask IntegrationTest { + if (Test-Path -Path $script:IntegrationTestsPath) { Write-Build White " Importing desired Pester version. Min: $script:MinPesterVersion Max: $script:MaxPesterVersion" Remove-Module -Name Pester -Force -ErrorAction SilentlyContinue # there are instances where some containers have Pester already in the session Import-Module -Name Pester -MinimumVersion $script:MinPesterVersion -MaximumVersion $script:MaxPesterVersion -ErrorAction 'Stop' - Write-Build White " Performing Pester Infrastructure Tests in $($invokePesterParams.path)" - + Write-Build White " Performing Pester Integration Tests in $($invokePesterParams.path)" - $pesterConfiguration = [PesterConfiguration]::new() - $pesterConfiguration.run.Path = $script:InfraTestsPath + $pesterConfiguration = New-PesterConfiguration + $pesterConfiguration.run.Path = $script:IntegrationTestsPath $pesterConfiguration.Run.PassThru = $true $pesterConfiguration.Run.Exit = $false $pesterConfiguration.CodeCoverage.Enabled = $false @@ -526,9 +521,9 @@ Add-BuildTask InfraTest { $numberFails = $testResults.FailedCount Assert-Build($numberFails -eq 0) ('Failed "{0}" unit tests.' -f $numberFails) - Write-Build Green ' ...Pester Infrastructure Tests Complete!' + Write-Build Green ' ...Pester Integration Tests Complete!' } -} #InfraTest +} #IntegrationTest #Synopsis: Creates an archive of the built Module Add-BuildTask Archive { diff --git a/src/pwshCloudCommands/Private/Confirm-XMLDataSet.ps1 b/src/pwshCloudCommands/Private/Confirm-XMLDataSet.ps1 index 225bfb8..f728f69 100644 --- a/src/pwshCloudCommands/Private/Confirm-XMLDataSet.ps1 +++ b/src/pwshCloudCommands/Private/Confirm-XMLDataSet.ps1 @@ -47,7 +47,7 @@ function Confirm-XMLDataSet { return $result } if ($fileData) { - $creationDate = $fileData.CreationTime + $creationDate = $fileData.LastWriteTime $now = Get-Date if (($now - $creationDate).Days -ge 9) { Write-Verbose 'Data file requires refresh.' diff --git a/src/pwshCloudCommands/Private/Invoke-XMLDataCheck.ps1 b/src/pwshCloudCommands/Private/Invoke-XMLDataCheck.ps1 index 0e76404..b570959 100644 --- a/src/pwshCloudCommands/Private/Invoke-XMLDataCheck.ps1 +++ b/src/pwshCloudCommands/Private/Invoke-XMLDataCheck.ps1 @@ -49,20 +49,27 @@ function Invoke-XMLDataCheck { $ConfirmPreference = 'None' $dataOutputDir = Confirm-DataLocation + if ($dataOutputDir -eq $true) { + $confirm = Confirm-XMLDataSet - if (-not ($Confirm -eq $true)) { + if (($Confirm -eq $false)) { + $retrieve = Get-XMLDataSet if ($retrieve -eq $true) { + $expand = Expand-XMLDataSet - if (-not ($expand -eq $true)) { + if ($expand -eq $false) { $results = $false } + } else { $results = $false } + } #if_Confirm + } #if_data_output else { $results = $false diff --git a/src/pwshCloudCommands/Public/Find-CloudCommand.ps1 b/src/pwshCloudCommands/Public/Find-CloudCommand.ps1 index 92b6045..c516f5e 100644 --- a/src/pwshCloudCommands/Public/Find-CloudCommand.ps1 +++ b/src/pwshCloudCommands/Public/Find-CloudCommand.ps1 @@ -1,54 +1,49 @@ <# .SYNOPSIS - Finds PowerShell cloud command(s) that match the provided query. + Searches for PowerShell cloud commands matching a given query. .DESCRIPTION - Performs query search on a dynamically updated cache of known PowerShell cloud commands. - Results are returned based on provided criteria. - Based on the query provided, a different form of search is performed. - If a function name is provided (Verb-Noun), a function name query is performed. - If a wildcard is provided (Ve*-Noun), a wildcard query is performed. - Anything else is treated as a free-form query. - Order of query efficiency is: - 1. Function name query - 2. Wildcard query - 3. Free-form query - Query performance will also be greatly increased if you filter to the specific cloud platform you are using (AWS/Azure/Oracle). - Free-form queries can generate many results and by default only the top 30 results are returned. - Use the -AllResults parameter with free-form queries to return all results. + This function searches a dynamically updated cache of PowerShell cloud commands, + returning results that match specific criteria. The nature of the search depends on the type of query: + - Function Name Query: Directly uses the function name format (Verb-Noun). + - Wildcard Query: Utilizes wildcards (e.g., Ve*-Noun) for broader searches. + - Free-form Query: Handles any other text as a general search term. + The efficiency of queries follows this order: function name, wildcard, then free-form. + Specifying a cloud platform (AWS/Azure/Oracle) enhances performance, especially for free-form queries. + By default, free-form queries return the top 30 results; use the -AllResults parameter to retrieve all matches. .EXAMPLE Find-CloudCommand -Query Write-S3Object -Filter AWS - Search for a specific function name (Verb-Noun) and filter to AWS. + Searches for the 'Write-S3Object' function specifically within AWS services. .EXAMPLE Find-CloudCommand -Query New-OCIComputeInstance -Filter Oracle - Search for a specific function name (Verb-Noun) and filter to Oracle. + Looks for the 'New-OCIComputeInstance' function within Oracle cloud services. .EXAMPLE Find-CloudCommand -Query New-MLDataSourceFromRedshift - Search for a specific function name (Verb-Noun) against all cloud platforms. + Searches for 'New-MLDataSourceFromRedshift' across all cloud platforms. .EXAMPLE Find-CloudCommand -Query New*VM* -Filter Azure - Wildcard function search that is filtered to Azure. + Performs a wildcard search for VM-related functions within Azure. .EXAMPLE Find-CloudCommand -Query Get*WAF* - Wildcard function search against all cloud platforms. + Uses a wildcard search for WAF-related functions across all platforms. .EXAMPLE Find-CloudCommand -Query 'I want to create a new compute instance' -Filter Oracle - Free-form query that is filtered to Oracle. + Conducts a free-form search related to compute instances in Oracle cloud. .EXAMPLE Find-CloudCommand -Query 'download an object from a S3 bucket' -Filter AWS -AllResults - Free-form query that is filtered to AWS and returns all results. + Executes a comprehensive free-form search for downloading objects from S3 in AWS. .PARAMETER Query - PowerShell cloud command search input + Search input for PowerShell cloud commands. .PARAMETER Filter - Filter results to specific cloud platform (AWS/Azure/Oracle) + Filters the search to a specific cloud platform (AWS/Azure/Oracle). .PARAMETER AllResults - Return all results, regardless of the number of results returned + Retrieves all search results without limiting the number. .NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ .COMPONENT @@ -65,21 +60,21 @@ function Find-CloudCommand { param ( [Parameter(Mandatory = $true, Position = 0, - HelpMessage = 'PowerShell cloud command search input')] + HelpMessage = 'Search input for PowerShell cloud commands.')] [ValidateLength(3, 60)] [string] $Query, [Parameter(Mandatory = $false, Position = 1, - HelpMessage = 'Filter results to specific cloud platform')] + HelpMessage = 'Filters the search to a specific cloud platform')] [ValidateSet('AWS', 'Azure', 'Oracle')] [string] $Filter, [Parameter(Mandatory = $false, Position = 2, - HelpMessage = 'Return all results')] + HelpMessage = 'Retrieves all search results without limiting the number')] [switch] $AllResults ) diff --git a/src/pwshCloudCommands/Public/Get-AllCloudCommandInfo.ps1 b/src/pwshCloudCommands/Public/Get-AllCloudCommandInfo.ps1 index c310ba9..c54fed3 100644 --- a/src/pwshCloudCommands/Public/Get-AllCloudCommandInfo.ps1 +++ b/src/pwshCloudCommands/Public/Get-AllCloudCommandInfo.ps1 @@ -1,19 +1,20 @@ <# .SYNOPSIS - Returns module and function information for all known PowerShell cloud commands. + Returns detailed module and function information on all available PowerShell cloud commands. .DESCRIPTION - Returns results from the entire PowerShell cloud command catalog. - It is recommended to use the Filter parameter to reduce the size of the result set. + This function provides comprehensive details on modules and functions from the entire catalog + of PowerShell cloud commands. To manage the volume of data returned, it's advisable to use the + 'Filter' parameter to focus on a specific cloud provider's commands. .EXAMPLE Get-AllCloudCommandInfo -Filter AWS - Returns module and function information of all known AWS PowerShell cloud commands. + Retrieves a complete list of modules and functions for AWS-specific PowerShell cloud commands. .EXAMPLE Get-AllCloudCommandInfo - Returns module and function information of all known PowerShell cloud commands. + Returns information on all available PowerShell cloud commands across various cloud platforms. .PARAMETER Filter - Filter results to specific cloud platform (AWS/Azure/Oracle) + Filters the search to a specific cloud platform (AWS/Azure/Oracle). .NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ .COMPONENT @@ -24,7 +25,7 @@ function Get-AllCloudCommandInfo { param ( [Parameter(Mandatory = $false, Position = 0, - HelpMessage = 'Filter results to specific cloud platform')] + HelpMessage = 'Filters the search to a specific cloud platform')] [ValidateSet('AWS', 'Azure', 'Oracle')] [string] $Filter diff --git a/src/pwshCloudCommands/Public/Get-CloudCommandFromFile.ps1 b/src/pwshCloudCommands/Public/Get-CloudCommandFromFile.ps1 index 90fd30b..98190a9 100644 --- a/src/pwshCloudCommands/Public/Get-CloudCommandFromFile.ps1 +++ b/src/pwshCloudCommands/Public/Get-CloudCommandFromFile.ps1 @@ -1,21 +1,22 @@ <# .SYNOPSIS - Evaluates PowerShell files in specified path and identifies a list of PowerShell cloud functions and their associated modules. + Identifies PowerShell cloud functions and modules within files at a specified path. .DESCRIPTION - Discovers all PowerShell files in the specified path. - Parses each file and identifies all PowerShell cloud functions and their associated modules. + This function scans and analyzes PowerShell files in a given directory or path. + It parses each file to identify all PowerShell cloud functions and their associated modules, + providing a comprehensive overview of cloud-related commands used in the project. .EXAMPLE $psCloud = Get-CloudCommandFromFile -Path "$env:HOME\pathToEvaluate" $psCloud - Returns a list of PowerShell cloud functions and their associated modules found in files in the specified path. + Examines the specified path for PowerShell files, returning a list of cloud functions and their modules found in these files. .EXAMPLE $psCloud = Get-CloudCommandFromFile -Path "$env:HOME\pathToEvaluate" $psCloud.CloudCommands.ModuleName | Select-Object -Unique - Returns a list of unique module names found in use in files in the specified path. + After analyzing files at the specified path, this returns a list of unique module names utilized in those files. .PARAMETER Path - File or Folder Path to evaluate. + File or directory path to be evaluated for cloud command usage. .OUTPUTS System.Management.Automation.PSCustomObject .NOTES @@ -28,7 +29,7 @@ function Get-CloudCommandFromFile { param ( [Parameter(Mandatory = $true, Position = 0, - HelpMessage = 'File or Folder Path to evaluate')] + HelpMessage = 'File or directory path to be evaluated for cloud command usage')] [string] $Path ) diff --git a/src/pwshCloudCommands/pwshCloudCommands.psd1 b/src/pwshCloudCommands/pwshCloudCommands.psd1 index d4077d0..184a76c 100644 --- a/src/pwshCloudCommands/pwshCloudCommands.psd1 +++ b/src/pwshCloudCommands/pwshCloudCommands.psd1 @@ -12,7 +12,7 @@ RootModule = 'pwshCloudCommands.psm1' # Version number of this module. - ModuleVersion = '0.8.0' + ModuleVersion = '1.0.0' # Supported PSEditions # CompatiblePSEditions = @() @@ -54,7 +54,7 @@ RequiredModules = @( @{ ModuleName = 'Convert' - ModuleVersion = '0.6.0' + ModuleVersion = '1.5.0' } )