Changing endpoint in Web.config during deployment with a Azure Powershell script - asp.net-mvc

I recently created a Powershell script that deploys my Web Application (ASP.NET MVC) to Azure. It works like it should, but I figured out that it would improve the script a lot by being able to change the endpoint in the Web.config file during deployment, i.e. the script prompts the user for the address. The Web.config section looks like this:
<system.serviceModel>
<client>
<endpoint address="http://localhost:10421/MyService" binding="binding" bindingConfiguration="foo" contract="bar" name="id" />
</client>
</system.serviceModel>
I would like to change the endpoint address with my script.

Use the Get-Content cmdlet to load your configuration file, access the property and change it and finally write it back using the Set-Content cmdlet:
[xml]$content = (Get-Content 'your_file')
$content.configuration.'system.serviceModel'.client.endpoint.address = 'YourNewAdress'
$content | Set-Content 'your_file'
Note: I asume that the system.serviceModel is within the configuration node. If not, omit that.

Related

Jenkins Windows Slave setup using Winsw not working

Using this info https://hayato-iriumi.net/2019/05/23/how-to-install-jenkins-slave-as-windows-service/ we are setting up the Jenkins Slave on Windows server. Jenkins agent start from command line. but when we start from Windows service, its giving below error message? How to resolve this error message?
Service cannot be started. System.IO.InvalidDataException: Attribute <className> is missing in configuration XML
at winsw.Util.XmlHelper.SingleAttribute[TAttributeType](XmlElement node, String attributeName)
at winsw.Extensions.WinSWExtensionDescriptor.FromXml(XmlElement node)
at winsw.Extensions.WinSWExtensionManager.LoadExtension(String id)
at winsw.Extensions.WinSWExtensionManager.LoadExtensions()
at winsw.WrapperService.OnStart(String[] args)
at System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(Object state)
xml file we have
<service>
<id>JenkinsSlave</id>
<name>Jenkins agent</name>
<description>This service runs an agent for Jenkins automation server.</description>
<executable>c:\java\jdk-11\bin\java.exe</executable>
<arguments>-Xrs -jar "c:\jenkins\slave.jar" -jnlpUrl https://jenkinsmaster/jenkins/computer/slave01/slave-agent.jnlp -secret a4b5b4ddfd34a016cd3a8eb94cbe8f908613e33a66db5fa6f5f43a080aea3116 -workDir=c:\jenkins</arguments>
<workingdirectory>c:\jenkins</workingdirectory>
<logmode>rotate</logmode>
<onfailure action="restart">
<download from="https://jenkinsmaster/jenkins/jnlpJars/slave.jar" to="c:\jenkins\slave.jar">
<extensions>
<extension enabled="false" classname="winsw.Plugins.RunawayProcessKiller.RunawayProcessKillerExtension" id="killOnStartup">
<pidfile>c:\jenkins\jenkins_agent.pid</pidfile>
<stoptimeout>5000</stoptimeout>
<stopparentfirst>false</stopparentfirst>
</extension>
</extensions>
</download>
</onfailure>
</service>
Thanks
There are some errors in the sample "Jenkins-Slave.xml" that is presented at the linked web page (which yours is apparently based on). It has all elements and attributes named in lowercase, but actually some of them should be mixed case (as can be seen by the error message that it doesn't find attribute className).
Try this one instead:
<service>
<id>YourJenkinsSlaveServiceId</id>
<name>Your Jenkins Slave Service Name</name>
<description>This service runs an agent for Jenkins automation server.</description>
<executable>C:\Program Files\Java\JRE8\bin\java.exe</executable>
<arguments>-Xrs -jar "%BASE%\slave.jar" -jnlpUrl http://YourJenkinsServer:8080/computer/YourNodeName/slave-agent.jnlp -secret YourSecretStringConsistingOfHexadecimalCharacters -workDir=C:\YourNodeWorkDir</arguments>
<logmode>rotate</logmode>
<onfailure action="restart" />
<download from="http://YourJenkinsServer:8080/jnlpJars/agent.jar" to="%BASE%\slave.jar"/>
<extensions>
<extension enabled="true" className="winsw.Plugins.RunawayProcessKiller.RunawayProcessKillerExtension" id="killOnStartup">
<pidfile>%BASE%\jenkins_agent.pid</pidfile>
<stopTimeout>5000</stopTimeout>
<stopParentFirst>false</stopParentFirst>
</extension>
</extensions>
</service>
This is from a more detailed explanation of how to install an agent as a Windows service which I have given in this answer.
I too has the same issue similarly..
System.IO.FileNotFoundException: Unable to locate jenkins.xml file within executable directory or any parents
at winsw.ServiceDescriptor..ctor()
at winsw.WrapperService.Run(String[] _args, ServiceDescriptor descriptor)
at winsw.WrapperService.Main(String[] args)
Solution:
Save your jenkins-agent file as xml format. not just jenkins-agent.xml
we can use notepad++ to save the xml type.
similarly remove .exe at end of jenkins-agent.exe
Hope its useful.... cheers !!
The className, stopTimeout and stopParentFirst should not be in lower case.

CloudConfigurationManager GetSetting - not getting value from cscfg when running in Azure

We have a setting defined in our Azure Cloud Service (csdef)
<ConfigurationSettings>
<Setting name="CDN" />
</ConfigurationSettings>
And it's value in the cscfg file
<ConfigurationSettings>
<Setting name="CDN" value="az12345.vo.msecnd.net" />
</ConfigurationSettings>
And in order for to work "outside" of Azure we have this in the web.config
<add key="CDN" value="localcdn" />
When the cloud service is deployed into Azure the value for CDN is "localcdn" and NOT the value that is in the cscfg file "az12345.vo.msecnd.net".
We have other cloud services with exactly the same setting which are resolved correctly, but this service refuses to.
My understanding from https://msdn.microsoft.com/en-us/library/microsoft.windowsazure.cloudconfigurationmanager.getsetting.aspx is that it will get the value from the cscfg when in Azure and web/app.config when it's not.
We are using Microsoft Azure Configuration Manager 3.1.0
Issue caused by Role Environment erroring

Nuget package to insert project name in web.config

I've created a Nuget package which inserts a key/value pair called ApplicationName in the web.config file with a default value of Application Name.
Is there a way to get the name of the .Net MVC project that a user would be installing the package into the value of the key/value in a human readable format? i.e. Incorrect: ApplicationName Correct: Application Name
If it's not possible to get the project name, I suppose using some sort of command line option could work?
After a few days of pondering, here is the solution I came up with.
Create a web.config transform file to add the key/value pair to the AppSettings section.
Create an install.ps1 file, that grabs the project name, parses it and injects the new value for AppplicationName in the web.config.
Here's my web.config.install.xdt file:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings xdt:Transform="InsertIfMissing">
<add key="ApplicationName" value="Application Name" xdt:Transform="InsertIfMissing" xdt:Locator="Match(key)" />
</appSettings>
</configuration>
Here's is my install.ps1 script:
# Runs every time a package is installed in a project
param($installPath, $toolsPath, $package, $project)
# $installPath is the path to the folder where the package is installed.
# $toolsPath is the path to the tools directory in the folder where the package is installed.
# $package is a reference to the package object.
# $project is a reference to the project the package was installed to.
$p = Get-Project
$project_readable_name = ($p.Name -creplace '([A-Z\W_]|\d+)(?<![a-z])',' $&').trim()
# Solution based on answer found on Stackoverflow: http://stackoverflow.com/questions/6901954/can-nuget-edit-a-config-file-or-only-add-to-it
$xml = New-Object xml
# Find the web.config
$config = $project.ProjectItems | where {$_.Name -eq "Web.config"}
if($config) {
# Find web.config's path on the file system
$localPath = $config.Properties | where {$_.Name -eq "LocalPath"}
# Load Web.config as XML
$xml.Load($localPath.Value)
# Select the ApplicationName node
$node = $xml.SelectSingleNode("configuration/appSettings/add[#key='ApplicationName']")
# Change the ApplicationName value
$node.SetAttribute("value", $project_readable_name)
# Save the Web.config file
$xml.Save($localPath.Value)
}
Hope this helps anyone else!

Creating a job with credentials in jenkins only in command lines

I am only allowed to work with the command line terminal on Ubuntu.
I need to create a job in Jenkins with security credentials.
I already installed Jenkins in my machine, but the access is open. If I set-up security credentials on Jenkins, how can I specify these on the command line?
Follow these steps:
Generate a public ssh-key in the user you want to work with from the command line:
ssh-keygen
Just press enter whenever yo are asked to enter some value.
Copy the content of the file ~/.ssh/id_rsa.pub.
Go to your jenkins home screen in a browser and login with a user with full access, Then click on the right on Users and then on the user you are currently logged with. Then click on settings (or configuration??).
In the field SSH public keys paste the content of the id_rsa.pub file. Save the changes.
And that's all! Now you are able to work with jenkins from the command line.
From the command line
The following is the configuration file of my jenkins main user (with all the privileges). Pay attention to the setting <authorizedKeys>. You should paste there the public ssh key. I haven't made that, but surely if you add the necessary lines to your config file it works. The file is in /path_to_jenkins/users/user_name/config.xml
<?xml version='1.0' encoding='UTF-8'?>
<user>
<fullName>admin</fullName>
<description></description>
<properties>
<jenkins.security.ApiTokenProperty>
<apiToken>pP08W9tzs2jlCrVCY9I2o6y2RNu3Huw85Y2f99/Uif7dia1W7piGpzsrpstln/jw</apiToken>
</jenkins.security.ApiTokenProperty>
<com.cloudbees.plugins.credentials.UserCredentialsProvider_-UserCredentialsProperty plugin="credentials#1.4">
<credentials/>
</com.cloudbees.plugins.credentials.UserCredentialsProvider_-UserCredentialsProperty>
<hudson.tasks.Mailer_-UserProperty plugin="mailer#1.4">
<emailAddress>admin#mail.com</emailAddress>
</hudson.tasks.Mailer_-UserProperty>
<hudson.model.MyViewsProperty>
<primaryViewName></primaryViewName>
<views>
<hudson.model.AllView>
<owner class="hudson.model.MyViewsProperty" reference="../../.."/>
<name>Alle</name>
<filterExecutors>false</filterExecutors>
<filterQueue>false</filterQueue>
<properties class="hudson.model.View$PropertyList"/>
</hudson.model.AllView>
</views>
</hudson.model.MyViewsProperty>
<hudson.security.HudsonPrivateSecurityRealm_-Details>
<passwordHash>1DF2ykjkkkjkkQXW</passwordHash>
</hudson.security.HudsonPrivateSecurityRealm_-Details>
<org.jenkinsci.main.modules.cli.auth.ssh.UserPropertyImpl>
<authorizedKeys>ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA4P1b/5RpibQgDZpKPD7lTQLjtyMrIQH43ns62PO72koL9zJe6qrAYcTIDNOUvSYNYyKfrgt6Z5zB8MvvENQLWezDKTWNXINhZml0PxOlc9ZaHbQX6UqyFbTS6o+ZEGs+K92Yi/XwK5hTmN5Igsw5BQYEs5cOsd5H2PoEZdhK1X0XAEBX/+p6aNy585+/scgZj0jSIvcX+pnzsCJLKmeYadlLnbrvebf9u6pu8MI9RuAY5dvPfpSL4WynWwS1QvY4z535TqPaaAlM3qXqH0pcOlxgW1iUkJqti3JnnxpBNXLmXalmq+4/d7mUrRBx+HKbh5ZpNZad9vaelAjAsNg+uw== user#machine_name</authorizedKeys>
</org.jenkinsci.main.modules.cli.auth.ssh.UserPropertyImpl>
<hudson.search.UserSearchProperty>
<insensitiveSearch>false</insensitiveSearch>
</hudson.search.UserSearchProperty>
</properties>
</user>
I just changed the starting prompt location to the folder in which the jar file is located. For example, if your jar file's location and name is:
C:\Users\Tod\file.jar
you can do two commands:
cd C:\Users\Tod
java -jar file.jar

How to specify default Application Pool in ASP.NET MVC Project?

In my ASP.NET MVC project I have added a parameters.xml file that looks like:
<?xml version="1.0" encoding="utf-8" ?>
<parameters>
<parameter name="Application Pool" description="Application Pool Name" defaultValue="PreferredPool">
<parameterEntry kind="DeploymentObjectAttribute"
scope="appHostConfig"
match="application/#applicationPool"/>
</parameter>
</parameters>
Then I go ahead and build the deployment package:
MSBuild.exe myproject.csproj /t:Package /p:PackageLocation="C:\packages\myproject.zip"
And then I invoke the batch script generated (myproject.deploy.cmd) and deploy the app to a local IIS 7 server. The problem is, it is always the Default Application Pool that is assigned to the app instead of the PreferredPool as specified in parameters.xml.
What did I do wrong?
Change your parameterEntry's scope to "application":
<parameterEntry kind="DeploymentObjectAttribute"
scope="application"
match="application/#applicationPool"/>

Resources