-
Notifications
You must be signed in to change notification settings - Fork 313
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Windows support! #69
Windows support! #69
Conversation
This role supports Consul 0.8.3 but still installs 0.8.2 by accident. This has been remedied.
@@ -86,37 +85,44 @@ the variables are named and described below: | |||
### `consul_bin_path` | |||
|
|||
- Binary installation path | |||
- Default value: `/usr/local/bin` | |||
- Default linux value: `/usr/local/bin` | |||
- Default windows value: `C:\ProgramData\consul\bin` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've used C:\ProgramData\consul
for all necessary program data, including the consul.exe binary. Most Windows programs use the magical %APPDATA%
path, but those are tied to specific users. My understanding is that C:\ProgramData
is what Chocolatey and NSSM use, and it's a good place for system-level services.
|
||
### `consul_user` | ||
|
||
- OS user | ||
- Default value: *consul* | ||
- Default linux value: *consul* | ||
- Default linux value: *LocalSystem* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Windows convention is to have the LocalSystem
user run services. It has the right mix of permissions for those kinds of services.
@@ -5,20 +5,26 @@ | |||
consul_debug: no | |||
|
|||
### Package | |||
consul_version: "{{ lookup('env','CONSUL_VERSION') | default('0.8.2', true) }}" | |||
consul_version: "{{ lookup('env','CONSUL_VERSION') | default('0.8.3', true) }}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last commit on the upstream repo updates the project to support Consul 0.8.3, but the default installation still downloads 0.8.2. This is an unrelated bug fix, but will probably just disappear if fixed upstream, correct?
consul_architecture_map: | ||
# this first entry seems... redundant | ||
#(but it's required for reasons) | ||
amd64: amd64 | ||
x86_64: amd64 | ||
armv7l: arm | ||
aarch64: arm64 | ||
32-bit: "386" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if there are even Windows Server versions that run in 32-bit, but there are personal versions of Windows that do, and this entry ensures the right package is grabbed from Hashicorp.
defaults/main.yml
Outdated
{% if ansible_os_family == "Windows" %}\ | ||
{{ 'windows' }}\ | ||
{% else %}\ | ||
{{ ansible_system | lower }}\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ansible_system
in these cases returns Win32NT. This changes between Windows Server versions and is unfortunately brittle.
@@ -27,6 +33,7 @@ consul_install_remotely: false | |||
consul_bin_path: "/usr/local/bin" | |||
consul_config_path: "/etc/consul" | |||
consul_configd_path: "/etc/consul.d" | |||
consul_bootstrap_state: "/etc/consul/.consul_bootstrapped" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bootstrap state is another path I needed to change for Windows, and consolidating it with the other paths seemed to be the smart choice.
defaults/main.yml
Outdated
consul_iface: "{{ lookup('env','CONSUL_IFACE') | default(ansible_default_ipv4.interface, true) }}" | ||
consul_iface: "\ | ||
{% if ansible_os_family == "Windows" %}\ | ||
{{ lookup('env','CONSUL_IFACE') | default(ansible_interfaces[0].interface_name, true) }}\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Network interfaces in Windows are handled very differently in Ansible, with very little overlap. I'm not sure why. But this works.
service: | ||
name: consul | ||
state: restarted | ||
include: restart_consul.yml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having OS-contextual handlers is awkward. I attempted to do this with ansible blocks but they're unsupported. This is clunkier than ideal, but is the best option I could find that works.
path: /tmp/consul | ||
state: directory | ||
|
||
- name: Verify TLS1.2 is used |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Windows attempts to use TLS1.0 by default when downloading files, falling back to SSL3, and never trying TLS1.2. This is fixed in later versions of Windows.
This task sets a typical value in the registry just in case it isn't there, ensuring that TLS1.2 is tried first, then TLS1.0, then SSL3. Otherwise, downloading the package and checksum files outright fails because you haven't changed the registry variable. ¯_(ツ)_/¯
when: not consul_checksum.stat.exists | bool | ||
|
||
- name: Read Consul package checksum | ||
win_shell: "findstr {{ consul_pkg }} /tmp/consul/consul_{{ consul_version }}_SHA256SUMS" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
findstr
is to Windows as grep
is to Linux.
dest: "/tmp/consul/{{ consul_pkg }}" | ||
tags: installation | ||
|
||
- name: Calculate checksum |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These next two tasks are done different from the usual path, because win_get_url
doesn't allow checksums like get_url
does. Minor inconsistency we have to handle by hand here.
include: config_windows.yml | ||
when: ansible_os_family == 'Windows' | ||
|
||
- name: Ensure neither ACL nor TLS are requested for windows hosts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small safety check. I haven't updated the ACL or TLS code, so in the meanwhile their support is turned off for Windows hosts. This can be added later.
@@ -157,10 +200,12 @@ | |||
group: root | |||
mode: 0755 | |||
when: | |||
- ansible_service_mgr is defined |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ansible_service_mgr
is undefined on Windows.
state: latest | ||
|
||
- name: Start Consul on Windows | ||
win_nssm: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NSSM is used to wrap consul.exe into a Windows-friendly service. Without it we can't use the regular win_service
module because services don't let you set configuration variables.
|
||
- name: Check Consul HTTP API | ||
wait_for: | ||
delay: 15 | ||
port: 8500 | ||
when: ansible_os_family != "Windows" | ||
|
||
- name: Check Consul HTTP API |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no win_wait_for
module yet. This is a hack to use wait_for
locally and watch the port in the same way. It works on my machine perfectly, but I can see cases where this could potentially fail depending on network setup. It may need more work in the future.
# File: Windows.yml - Windows OS variables for Consul | ||
|
||
# paths | ||
consul_windows_path: /ProgramData/consul |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fun fact: forward slashes now work almost as well as backslashes do in Windows! Folder structure is still different though.
Thanks very much for this contribution! |
- name: Install NSSM | ||
win_chocolatey: | ||
name: nssm | ||
state: latest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@judy @brianshumate Shouldn't there be a when clause here checking for os_family == "Windows"?
(Didn't test)
Heads up; the "when" clauses are breaking anything that registers objects in the output (e.g. stat) as the condition failure is being stored in register and forcibly casting as a dict. Might just be an ordering problem; it's likely best to encapsulate the Windows & non-Windows stuff inside a block. |
Yeah... missed that stuff, sorry! I have committed a quick change that puts all non-Windows and Windows main tasks in separate top-level blocks. Not the ideal solution, but it unbreaks the role for the moment. This is released in v1.20.1 also. |
I was trying this earlier but wasn't formatting my |
👍 |
I wrote full Windows support for this role. I tried to match the programming style and Ansible best practices as closely as possible. I'm still new to Ansible, and would happily accept any feedback.
There are a LOT of additions, and more than a handful of changes, mostly
ansible_os_system
checks. I'll comment in the code diff where there might be points of confusion between how Linux does things and how Windows does them.