Upload
jhawkesworth
View
2.936
Download
4
Embed Size (px)
Citation preview
Jon Hawkesworth
Hello
● Background: Support → Dev, scripting then java. Web services
● Coding: Bourne Shell → perl → java → whatever works
● A bit Ops too: Dev Admin. Dev tools, jenkins, wikis, Webmin modules
● Ansible since July 2014
What?
● Getting stuff done on Windows boxes with Ansible
State of play
● Modules - in the bag– win_chocolatey (E) - Installs packages using chocolatey
– win_feature - Installs and uninstalls Windows Features
– win_get_url - Fetches a file from a given URL
– win_group - Add and remove local groups
– win_msi - Installs and uninstalls Windows MSI files
– win_ping - A windows version of the classic ping module.
– win_service - Manages Windows services
– win_stat - returns information about a Windows file
– win_updates (E) - Lists / Installs windows updates
– win_user - Manages local Windows user accounts
State of play 2
● Common modules– Raw, script, setup, slurp
● Controller-hosted (local_action) modules– uri, template
Still cooking
● Connecting as domain/NTLM user– Testable now.
● Modules: win_copy, win_file, win_template, win_unzip
– Awaiting 'v2' refactor
● win_package
“Patterns”
● Tactical, not necessarily idempotent● Patterns
– Phone Home
– Local Template
– Registry update
– Update MSI
– Embedded C#
Windows patterns – Phone Home
● 'Phone home' to get files.● Winrm web services
+ security, minimal resource usage but
– raw file transfer speed
● Use win_get_url to make managed hosts collect binaries/data.
– Avoids 'second hop' issue.
● Tip: mongoose http://cesanta.com/mongoose.shtml● Gotchas
– win_get_url is http only ATM, always 'changed'
Windows patterns – local template
● Use local_action with template to create host-specific configuration files.
● Gotchas: – templated files have u*x line endings
– Workaround: set line endings in template.j2:
#jinja2: newline_sequence:'\r\n'
{{ templated_var1 }}
{{ templated_var2 }}
Windows patterns – Modify Registry
● Export & edit relevant registry entries to file.
● win_get_url to collect registry files
● Import using reg.exe
- raw: "reg.exe IMPORT C:\\staging\\current\\my-app-settings.reg"
● Gotchas: – 'registry redirection' - 32bit/64bit 'views' of registry
– raw – will always report 'changed'
Windows patterns – update msi
● script - uninstall msi by name
● uri – query the build server for latest build / version number
● win_get_url – fetch latest msi from build server
● win_msi – install new msi
● Gotchas– win_package may simplify.
---
# Windows Patterns example, update to latest version of My App MSI
- name: Remove any old version of the application by name
script: uninstallMsi.ps1 "My App"
- name: Retrieve latest build information from jenkins build server
uri: "url={{ latest_build_url_base }}/api/json?tree=actions[parameters[value,number]] method=GET return_content=yes"
delegate_to: localhost
register: build_params
- name: tip - use debug to work out what bits of the json response you need.
- debug: var=build_params.json
# Windows Patterns example, continued..
- name: Set a fact to hold the product and build numbers
set_fact: version_build="{{ build_params.json.actions[0].parameters[0].value }}-{{ build_params.json.actions[0].parameters[1].number }}"
- name: Phone home to fetch the msi for the build we want
win_get_url:
url: "{{ latest_build_url_base }}artifact/msi/Myl%20App-{{version_build}}-DEV.msi"
dest: 'C:\staging\current\My App-{{ version_build }}-DEV.msi'
- name: install the msi from the download location
win_msi:
path: 'C:\staging\current\My App-{{ version_build }}-DEV.msi'
creates: 'C:\Program Files (x86)\My App Corporation\My App\My App.exe'
Windows patterns – embed c#
● Powershell scripts can contain c# code
$class=@"
public static class MyUsefulClass {
// useful c# class goes here
}
“@
Add-Type -TypeDefinition $class
[myusefulclass]::Method($param1,$param2);
● Gotchas
– Comma to separate args, unlike Powershell functions where comma separates array members.
Powershell for Ansiblists
● JEPTBD ● Just Enough Powershell To Be Dangerous
1 Pick Powershell Version
● Ansible Powershell 3.0 onwards● Windows 7 comes with 2.0 but 3.0 or 4.0 can be
installed● Server 2012 R2 comes with 4.0
Find Powershell version:
$PSVersionTable.PSVersion
or facts
2 Use Powershell ISE
● Tab completion, syntax highlighting
● Mount your controller /etc/ansible or pass via source control
3 Get-Help
● Shell script – shell built-ins and toolbox commands,
e.g. echo, grep, cut, sed, awk
● Powershell toolbox equivalent is Cmdlets
e.g. Write-Host, Select-String, Get-Content
● Cmdlets? Verb-Noun
Get-Help Cmdlet
● Aliases – examples:
– echo → Write-Output
– ls → Get-ChildItem
● To list Get-Alias
4 Understand Powershell pipe
● ps -ef | grep python
● Text stream from ps -ef is passed into grep
● Powershell pipes objects, not text
ls *.gv | foreach {
$newname = $_.BaseName + ".svg"
$args = @('-Tsvg', $_.FullName, "-o", $newname)
& 'dot.exe' $args
}
5 Understand Powershell 'return'
● Inside a function, return means 'put this in the output pipe'
● But... unless handled, other commands can add objects to the output pipe
function CheckParameterIsOne($parameter) {
echo "Checking parameter is one"
return $parameter -eq 1
}
if(CheckParameterIsOne(2)){
echo "Parameter was one"
} else {
echo "Parameter was not one"
}
echo – alias for Write-Output (writes to output pipe) so function outputs “Checking parameter is one” AND the result of the $parameter -eq 1 test.
6 Running .exe from Powershell
● 9 different ways to run executables from Powershell.● Args containing spaces can be tricky. Build an args
array. Be aware of auto quoting when calling from Ansible script.
● & limitations● Start-Process -Wait● Trap or try/catch to handle .exes that return non-zero
exit codes
Running a .exe example# Because the product name contains spaces, turn all the args into a string to get the product name (ansible arg quoting)
$ProductName = [string]$args -join ' ';
$Apps = Get-ItemProperty "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*",` #32-Bit
"HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*" #64-bit
$RemProg = $Apps | Where { $_.DisplayName -like "*$($ProductName)*" }
$ArgList = "/x $(($RemProg).PSChildName) /QN "
If($RemProg -gt $Null){ Start-Process MSIExec $ArgList -Wait }
Writing Powershell Ansible Modules
● # WANT_JSON● # POWERSHELL_COMMON
– Pulls in common code for returning json, checksum
● Module pattern– Check arguments
– Do module stuff
– Create a result object
Result object example$result = New-Object psobject @{
changed = $FALSE
another_useful_var = $useful_var
};
● Success:
Exit-Json $result
● Error:
Fail-Json (New-Object psobject) "helpful failure message";
● Changed: $TRUE → changed: [myHost]
$FALSE → ok: [myHost]
Debugging Powershell Modules
● ansible-playbook -vvvvv (includes all STDERR)
● Use export ANSIBLE_KEEP_REMOTE_FILES=1
● Remote files in user's temp dir, typically
C:\Users\<userYouAreRunningAs>\AppData\Local\Temp\ansible-tmp-nnnnnnnnnnn\
● Beware tab complete
.\mymodule.ps1 .\arguments
instead run
.\mymodule.ps1 arguments
Summing up
● Hope I've shown you can get a lot done with the current set of modules
● V2 a great time to jump in and contribute modules● You now know enough Powershell to be
dangerous. Be safe out there!● Thanks.
Links
● Learning Powershell
https://technet.microsoft.com/en-us/library/cc281945(v=sql.105).aspx
● The 9 ways of running executables in Powershell:
http://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.asp
● Error handling:
https://rkeithhill.wordpress.com/2009/08/03/effective-powershell-item-16-dealing-with-errors/
● Powershell 4.0 Core Cmdlets
https://technet.microsoft.com/en-us/library/hh849695.aspx