I have a DSC resource that installs dotnet feature and then installs an update to dotnet.
In the Local Configuration Manager I have set RebootNodeIfNeeded to $true.
After dotnet installs, it does not request a reboot (even used xPendingReboot module to confirm this).
Configuration WebServer
{
WindowsFeature NetFramework45Core
{
Name = "Net-Framework-45-Core"
Ensure = "Present"
}
xPendingReboot Reboot
{
Name = "Prior to upgrading Dotnet4.5.2"
}
cChocoPackageInstaller InstallDotNet452
{
name = "dotnet4.5.2"
}
}
This is a problem as dotnet doesn't work properly with our app unless the server has been rebooted and we are trying to make these reboots happen automatically no user input required.
Is there any way to make a resource push to the localdscmanager (LCM) that it needs a reboot when there's something being installed?
I have found the below command
$global:DSCMachineStatus = 1
Which sets a reboot. but I'm unsure as to how to use it to reboot right after the 4.5 module is installed.
Normally when I install .Net it works without rebooting, but if you want to force your configuration to reboot it after it installs it you can do the following. It won't work for drift (.net being removed after initial installation.) During configuration drift, the configuration will still install .net, but the script resource I added to reboot will believe it has already rebooted.
The DependsOn is very important here, you don't want this script running before the WindowsFeature has run successfully.
configuration WebServer
{
WindowsFeature NetFramework45Core
{
Name = "Net-Framework-45-Core"
Ensure = "Present"
}
Script Reboot
{
TestScript = {
return (Test-Path HKLM:\SOFTWARE\MyMainKey\RebootKey)
}
SetScript = {
New-Item -Path HKLM:\SOFTWARE\MyMainKey\RebootKey -Force
$global:DSCMachineStatus = 1
}
GetScript = { return #{result = 'result'}}
DependsOn = '[WindowsFeature]NetFramework45Core'
}
}
To get $global:DSCMachineStatus = 1 working, you first need to configure Local Configuration Manager on the remote node to allow Automatic reboots. You can do it like this:
Configuration ConfigureRebootOnNode
{
param (
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[String]
$NodeName
)
Node $NodeName
{
LocalConfigurationManager
{
RebootNodeIfNeeded = $true
}
}
}
ConfigureRebootOnNode -NodeName myserver
Set-DscLocalConfigurationManager .\ConfigureRebootOnNode -Wait -Verbose
(code taken from colin's alm corner)
Related
I am trying to execute a process which is written in c# through jenkins pipeline during the build and deployment process.
It is a simple executable which takes 3 arguments, when it gets called from jenkins pipeline using a powershell function it doesn't write any logs which are plenty within the code of this exe, also it does not show anything on the pipeline logs as to what happened to this process. Whereas the logs output is clean before and after the execution of this process i.e. "Started..." & "end" gets printed in the jenkins build log.
When i try to run the same exe on a server directly with the same powershel script it runs perfectly fine. Could you please let me know how can i determine whats going wrong here or how can i make the logs more verbose so i can figure out the root cause.
Here is the code snippet
build-utils.ps1
function disable-utility($workspace) {
#the code here fetches the executable and its supporting libraries from the artifactory location and unzip it on the build agent server.
#below is the call to the executable
Type xmlPath #this prints the whole contents of the xml file which is being used as an input to my exe.
echo "disable exe path exists : $(Test-Path ""C:\Jenkins\workspace\utils\disable.exe"")" // output is TRUE
echo "Started..."
Start-Process -NoNewWindow -Filepath "C:\Jenkins\workspace\utils\disable.exe" -ArgumentList "-f xmlPath 0" #xmlPath is a path to a xml file
echo "end."
}
jenkinsfile
library {
identifier: 'jenkins-library#0.2.14',
retriever: legacySCM{[
$class: 'GitSCM',
userRemoteConfigs: [[
credtialsId: 'BITBUCKET_RW'
url: <htps://gitRepoUrl>
]]
]}
}
def executeStep(String stepName) {
def butil = '.\\build\\build-utils.ps1'
if(fileExists(butil))
{
def status = powershell(returnStatus: true, script: "& { . '${butil}'; ${stepName}; }")
echo status
if(status != 0) {
currentBuild.Result = 'Failure'
error("$StepName failed")
}
}
else
{
error("failed to find the file")
}
}
pipeline {
agent {
docker {
image '<path to the docker image to pull a server with VS2017 build tools>'
lable '<image name>'
reuseNode true
}
}
environment {
#loading the env variables here
}
stages {
stage {
step {
executeStep("disable-utility ${env.workspace}")
}
}
}
}
Thanks a lot in advance !
Have you changed it ? go to Regedit [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System Set "EnableLUA"= 0
I'm running a PowerShell Function App (~3) which uses the Az PowerShell module to manage a Storage Account. If any of the operations I carry out result in an error, I am unable to check for specific types in a try/catch block.
It is important to note that where there is no error, operations using the Az.Storage module are successful.
For example, if I were to try and delete a container that does not exist, the example below results in the following error -
Unable to find type [Microsoft.WindowsAzure.Commands.Storage.Common.ResourceNotFoundException].
To obtain the type of exception that is returned, I'm using $_.Exception.GetType().fullname.
I've also tried to add the namespace to the script that may produce the exceptions.
using namespace Microsoft.WindowsAzure.Commands.Storage.Common
Example
Class Storage
{
[AppSettings]$AppSettings = [AppSettings]::GetInstance()
[Object]$Context
Storage()
{
$key = Get-AzStorageAccountKey -ResourceGroupName $this.AppSettings.StorageAccountResourceGroup -Name $this.AppSettings.StorageAccountName
$this.Context = New-AzStorageContext -StorageAccountName $this.AppSettings.StorageAccountName -StorageAccountKey $key[0].Value
}
[void] DeleteBlobContainer([String]$name)
{
try {
Remove-AzStorageContainer -Name $name -Context $this.Context -Force -ErrorAction Stop
}
catch [Microsoft.WindowsAzure.Commands.Storage.Common.ResourceNotFoundException] {
throw [ContainerNotFoundException]::new($name)
}
catch {
throw [DustBinException]::new($_.Exception.Message)
}
}
}
Update
When calling an HTTP triggered function, I am able to see that the Az.Storage module is installed. This is expected, given operations that require the module are successful -
Get-Module -Name Az.Storage -ListAvailable | Select-Object Name, Version, ModuleBase | ConvertTo-Json
[
{
"Name": "Az.Storage",
"Version": {
"Major": 3,
"Minor": 0,
"Build": 0,
"Revision": -1,
"MajorRevision": -1,
"MinorRevision": -1
},
"ModuleBase": "C:\\Users\\dgard\\AppData\\Local\\AzureFunctions\\DustBin\\ManagedDependencies\\201202095548376.r\\Az.Storage\\3.0.0"
}
]
However, if copy the module to .\bin and include a Module manifest to require Microsoft.Azure.Storage.Common.dll, as suggested in this question, the type is still not found.
New-ModuleManifest ./Modules/StorageHelper/StorageHelper.psd1 -RootModule StorageHelper.psm1 -RequiredAssemblies .\bin\Az.Storage\3.0.0\Microsoft.Azure.Storage.Common.dll
To be sure I was adding the correct assembly, I have updated the manifest to include every single assembly in the Az.Storage module, but the type is still not found.
In my question I added an update mentioning that I had tried to add a module manifest requiring all of the Az.Storage assemblies; this was not quite correct...
I had copied the list of required assemblies from the module manifest included with the Az.Storage module, but this did not include Microsoft.Azure.PowerShell.Cmdlets.Storage.dll. Using a module manifest to require this assembly (just this one, no others required) has worked.
New-ModuleManifest ./Modules/StorageHelper/StorageHelper.psd1 -RootModule StorageHelper.psm1 -RequiredAssemblies .\bin\Az.Storage\3.0.0\Microsoft.Azure.PowerShell.Cmdlets.Storage.dll
My goal is to create a Powershell DSC configuration to unzip a file - from my local computer - to a remote directory on a Hyper-V Win10 VM (I've already shared that destination folder). But, right now, I still have some problem to insert the VM credentials inside the .ps1. This is my code:
Configuration CopyTest {
Node 'localhost'
{
User Admin
{
UserName = "Admin"
Password = "Password"
Ensure = "Present"
}
Archive ArchiveExample {
Ensure = 'Present'
Path = 'C:\Users\myuser\Documents\test.zip'
Destination = '\\DESKTOP-HEFLNJ6\destination'
}
}
}
Can anyone suggest me a way to insert the Windows credentials (of the remote machine) inside the Powershell script?
Thanks for your time...hope you can help!
you will have to use credential in you DSC configuration.
Below documentations will help you to achieve it.
https://learn.microsoft.com/en-us/powershell/dsc/runasuser
below is a small example which uses credential in a DSC configuration.
configuration FileCopy
{
Param(
[PSCredential]$Credential
)
node localhost
{
File CopyFile{
Ensure = 'Present'
DestinationPath = '\\server\share'
SourcePath = 'c:\sourcepath'
PsDscRunAsCredential = $Credential
}
}
}
I need to validate agent like memory, processor, and port connectivity before running my other manifest files. So I've created a manifest like following by keeping global facts with and statement and exec resource.
class vc {
#Validateing Infra Before applying chnages
if $::facts['memorysize'] >= '4.00 GiB'and $::facts['processorcount'] >= 2 and Exec['port_connectivity'] {
notify { "Infra validated" : }
include vc::configs
}
else {
notify { "Infra not meeting requirements" : }
}
# Checking port connecitivity to puppet master
exec { 'port_connectivity':
command => 'New-Item c:\debug.txt -type file -Force',
unless => 'if((New-Object System.Net.Sockets.TcpClient ("linux-NAS-storage.com",6163)).connected -eq $true) { exit 1 }',
provider => powershell,
}
}
my theme is puppet should only execute if this if $::facts['memorysize'] >= '4.00 GiB'and $::facts['processorcount'] >= 2 and Exec['port_connectivity'] condition was successful. If exec command was successful and facter returns true then only it should execute, but following manifest executing individually without checking whether that exec statement true or not. My main purpose I need to validate ports before running puppet manifest. Can any please help
I have a DSC configuration which install nodejs, adds npm to environment Path variable and then installs a npm module.
xPackage InstallNodeJs {
Name = 'Node.js'
Path = "$env:SystemDrive\temp\node-v4.4.7-x64.msi"
ProductId = '8434AEA1-1294-47E3-9137-848F546CD824'
Arguments = "/quiet"
}
Environment AddEnvironmentPaths
{
Name = "Path"
Ensure = "Present"
Path = $true
Value = "$env:SystemDrive\ProgramData\npm"
}
Script UpgradeNpm {
SetScript = {
& npm install --global --production npm-windows-upgrade
& npm-windows-upgrade --npm-version 3.10.6
}
TestScript = {
$npmVersion = & npm -v
return $npmVersion -eq "3.10.6"
}
GetScript = {
return {#{Result = "UpgradeNpm"}}
}
}
Installing nodejs and adding npm to Path variable seems to be successful. Both nodejs and npm location are added to Path and I can use them both in powershell and cmd.
However, Script resource returns that 'npm' is not recognized as internal or external command ...
the same is for node which is used inside npm-windows-upgrade script file.
Do you know why Script resource cannot read newly added Path entires?
The Environment DSC resource implementation makes the change by updating the values stored in the registry (with the exception of variables targeting Process). Changes made to environment variables stored in the registry are not reflected in the current session (read once, on session start).
You can affect values stored in the current session by:
Using System.Environment.SetEnvironmentVariable ([System.Environment]::SetEnvironmentVariable)
Modifying $env:<VariableName>
Of those, only the first allows you to write a persistent change. The latter can be considered a volatile change.
It's an odd limitation of the resource, I've looked at this before and felt it a little lacking.
There's no dependency information in there, so you can't count on the Environment resource running before the Script resource. There's not enough information in your post to tell if that's the case for sure, but you should consider controlling it anyway:
xPackage InstallNodeJs {
Name = 'Node.js'
Path = "$env:SystemDrive\temp\node-v4.4.7-x64.msi"
ProductId = '8434AEA1-1294-47E3-9137-848F546CD824'
Arguments = "/quiet"
}
Environment AddEnvironmentPaths
{
Name = "Path"
Ensure = "Present"
Path = $true
Value = "$env:SystemDrive\ProgramData\npm"
DependsOn = '[xPackage]InstallNodeJs'
}
Script UpgradeNpm {
SetScript = {
& npm install --global --production npm-windows-upgrade
& npm-windows-upgrade --npm-version 3.10.6
}
TestScript = {
$npmVersion = & npm -v
return $npmVersion -eq "3.10.6"
}
GetScript = {
return {#{Result = "UpgradeNpm"}}
}
DependsOn = '[Environment]AddEnvironmentPaths'
}
Can you share which version of DSC you are using? You can get this by doing a $PSVersionTable on the PowerShell console. I am able to add to the PATH variable and use it in a script resource.
configuration NPMTest
{
Environment AddEnvironmentPaths
{
Name = 'Path'
Ensure = 'Present'
Path = $true
Value = "$env:SystemDrive\ProgramData\npm"
}
Script p
{
GetScript = {#{}}
TestScript = {return $false}
SetScript = {$a = & a.ps1 ; Write-Verbose $a -Verbose}
}
}
The script a.ps1 was executed fine even though I am not specifying the full path to the script.