This tutorial is outdated. This was originally written is for Otter v2, which is not the current version of Otter. Stay tuned, an updated tutorial will be coming soon!
This tutorial will walk through the process of deploying a Windows Service application package from a ProGet Universal Feed to a server that will be set up and provisioned within Otter. A simple application setup like this is often the first step towards incremental adoption of a robust, Infrastructure as Code practice.
Before deploying an application using Otter, you need to bundle all of the executables, DLL’s, configuration files, installation scripts, etc. Anything the application needs will be put into a package.
proget.exe, or your own script to create a Universal Package (.upack) file.
Once a package is created, simply push it to the Feed Endpoint URL in ProGet using NuGet.exe, proget.exe, or a simple HTTP POST.
Note: if you publish an OctoPacked NuGet package, it will be automatically converted by the ProGet server to a Universal Package.
However the package gets there, the end result will look something like this:
The first is the ProGet endpoint (in case you set it up as an authenticated feed), and the second is the Windows or Active Directory account that the service will un under (alternatively, you can just configure the service to use Network Service instead).
localhostand select “Local” for the “Agent type:” > Save Server
Otter makes it easy to create configuration plans using its visual editor, allowing you to drag-and-drop elements to create a plan and only edit the parts you need. Otter’s Ensure Windows Service, Ensure IIS App Pool, and other operations offer all of the configuration options available, allowing for total control when needed.
A sample plan is shown below using four elements contained in a General Block that will deploy this service. Notice that there is parity between the Visual Editor version and the OtterScript version.
As soon as you save this plan, Otter’s execution engine will first perform a “collection run.”
In this run, the ensure operations will only gather configuration from a server, and then store that configuration and report if it is different from the desired configuration. Since this is the first time the configuration is run, this will put server in drift status.
From there, you can schedule a job to remediate the drift. When a remediation job is run, the “blocks” where configuration drift was detected will run. So in this case, the first step will be to stop the service so that the changed files can be copied as needed. Since the last operation is Ensure-Service, and we want to ensure the Status is Running, the service will be restarted as its final step.
A server can also be set to auto-remediate, so that any time configuration is drifted, Otter will automatically run the entire plan again to bring the drifted servers back into the expected status.
Since this deployment is happening in an Infrastructure as Code methodology, and using ensure statements, it is continuously monitored. In short, an ensure statement:
This means if a new version of the application is pushed to ProGet, because the Ensure-Package statement was used with the qualifier
latest, Otter will see that the
configuration on the server is not as defined, and the server will be considered in drift status.
At this point, redeploying just takes a remediation job, or can be set to auto-remediate.
On the same note, if you change a setting in the application’s .config file (note: this could also be defined as an environment, role, or server variable), it will also cause a drift status.
This tutorial is just a quick preview of what an Infrastructure as Code methodology can offer; from here, there’s a lot more to explore!
In the example above, a single server was directly configured; however, it would have been just as easy to create the plan as a server role plan to allow for provisioning multiple servers at the same time with the same plan, and increased flexibility.
Templates are plans stored as assets that can be executed by other plans similar to calling a function in traditional code. Combined with the power of variables and resource credentials, templates can be used to ensure various configurations with minimal duplication across server or server role configuration plans.
As noted, Otter continuously monitors your servers for configuration drift and can either:
This option is configurable per server, and monitoring can be set at specific intervals, determined by your infrastructure priority.
When report only is configured, you can schedule a configuration job to run immediately or at some time in the future.
You can even run a configuration job as a simulation, so that no changes are made to the drifted server, but a log is created with changes that would have been made. This is often a must-have for complex, or multi-role configurations to assist in testing, but might not be needed for simple applications.
Of course, a plan like this isn’t limited to .NET and Windows; it would be the same for any application package in any language.
Jenkins, TeamCity, and other CI tools can bundle files into formats that can easily be .upack formatted and then stored in ProGet, allowing for easy expansion no matter what build platform is being used.