27
Jon Hawkesworth

Ansible windows and powershell - AnsibleFest London 2015

Embed Size (px)

Citation preview

Page 1: Ansible windows and powershell  - AnsibleFest London 2015

Jon Hawkesworth

Page 2: Ansible windows and powershell  - AnsibleFest London 2015

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

Page 3: Ansible windows and powershell  - AnsibleFest London 2015

What?

● Getting stuff done on Windows boxes with Ansible

Page 4: Ansible windows and powershell  - AnsibleFest London 2015

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

Page 5: Ansible windows and powershell  - AnsibleFest London 2015

State of play 2

● Common modules– Raw, script, setup, slurp

● Controller-hosted (local_action) modules– uri, template

Page 6: Ansible windows and powershell  - AnsibleFest London 2015

Still cooking

● Connecting as domain/NTLM user– Testable now.

● Modules: win_copy, win_file, win_template, win_unzip

– Awaiting 'v2' refactor

● win_package

Page 7: Ansible windows and powershell  - AnsibleFest London 2015

“Patterns”

● Tactical, not necessarily idempotent● Patterns

– Phone Home

– Local Template

– Registry update

– Update MSI

– Embedded C#

Page 8: Ansible windows and powershell  - AnsibleFest London 2015

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'

Page 9: Ansible windows and powershell  - AnsibleFest London 2015

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 }}

Page 10: Ansible windows and powershell  - AnsibleFest London 2015

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'

Page 11: Ansible windows and powershell  - AnsibleFest London 2015

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.

Page 12: Ansible windows and powershell  - AnsibleFest London 2015

---

# 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

Page 13: Ansible windows and powershell  - AnsibleFest London 2015

# 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'

Page 14: Ansible windows and powershell  - AnsibleFest London 2015

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.

Page 15: Ansible windows and powershell  - AnsibleFest London 2015

Powershell for Ansiblists

● JEPTBD ● Just Enough Powershell To Be Dangerous

Page 16: Ansible windows and powershell  - AnsibleFest London 2015

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

Page 17: Ansible windows and powershell  - AnsibleFest London 2015

2 Use Powershell ISE

● Tab completion, syntax highlighting

● Mount your controller /etc/ansible or pass via source control

Page 18: Ansible windows and powershell  - AnsibleFest London 2015

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

Page 19: Ansible windows and powershell  - AnsibleFest London 2015

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

}

Page 20: Ansible windows and powershell  - AnsibleFest London 2015

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.

Page 21: Ansible windows and powershell  - AnsibleFest London 2015

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

Page 22: Ansible windows and powershell  - AnsibleFest London 2015

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 }

Page 23: Ansible windows and powershell  - AnsibleFest London 2015

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

Page 24: Ansible windows and powershell  - AnsibleFest London 2015

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]

Page 25: Ansible windows and powershell  - AnsibleFest London 2015

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

Page 26: Ansible windows and powershell  - AnsibleFest London 2015

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.

Page 27: Ansible windows and powershell  - AnsibleFest London 2015

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