-
Notifications
You must be signed in to change notification settings - Fork 321
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
Fix windows default paths #326
Conversation
164d2c2
to
c95cb9c
Compare
@glennsarti would be quite keen to get your input here |
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.
A bunch of things to change;
- Excessive use of PATH changes seems un-needed
- Using top level scope variables for facts instead of
$facts
- Dangerous path changes using TEMP directories
- Non-idempotent resources
manifests/compose.pp
Outdated
@@ -55,26 +55,24 @@ | |||
$docker_download_command = "if (Invoke-WebRequest ${docker_compose_url} ${proxy_opt} -UseBasicParsing -OutFile \"${docker_compose_location_versioned}\") { exit 0 } else { exit 1}" | |||
|
|||
exec { 'Enable TLS 1.2 in powershell': |
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.
This whole exec probably isn't required. IIRC this only affects the current process and you may as well just add this to the PS1 template files instead of a resource in of itself. This also will have no affect on older powershell module (1.x)
manifests/compose.pp
Outdated
exec { "Install Docker Compose ${version}": | ||
path => ['c:/Windows/Temp/', 'C:/Program Files/Docker/'], | ||
command => "& ${script_path}", | ||
path => ["${::systemroot}/Temp/", "${::program_files_path}/Docker/"], |
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.
Path is not required here as the template file itself uses absolute paths.
side note - Also "${::systemroot}/Temp/"
is not what you want. That is the TEMP environment for the SYSTEM account. If puppet runs under a different account (which is common enough) then the TEMP path is different.
provider => powershell, | ||
creates => $docker_compose_location_versioned, | ||
} | ||
|
||
file { $docker_compose_location: |
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.
nit: Can't say I'm a fan of symlinks as it's not Windows-y but I guess it will do.
manifests/compose.pp
Outdated
@@ -55,26 +55,24 @@ | |||
$docker_download_command = "if (Invoke-WebRequest ${docker_compose_url} ${proxy_opt} -UseBasicParsing -OutFile \"${docker_compose_location_versioned}\") { exit 0 } else { exit 1}" | |||
|
|||
exec { 'Enable TLS 1.2 in powershell': | |||
path => ['c:/Windows/Temp/', 'C:/Program Files/Docker/'], | |||
path => ["${::systemroot}/Temp/", "${::program_files_path}/Docker/"], | |||
command => '[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12', | |||
provider => powershell, | |||
creates => $docker_compose_location_versioned, |
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.
If you keep this resource in, this is not idempotent. this resource can never create the $docker_compose_location_versioned
file.
manifests/exec.pp
Outdated
$exec_timeout = 3000 | ||
$exec_path = ['c:/Windows/Temp/', 'C:/Program Files/Docker/'] | ||
$exec_path = ["${::systemroot}/Temp/", "${::program_files_path}/Docker/"] |
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 think any of this is required.
- See above. Systemroot\temp is not what you want.
- In fact there is no way you want %TEMP% to be first in the executable path. That is a security risk.
- $docker::params::docker_command should contain the absolute path, not a relative one. As you're using absolute paths everywhere else.
manifests/image.pp
Outdated
@@ -38,11 +38,11 @@ | |||
|
|||
if $::osfamily == 'windows' { | |||
$update_docker_image_template = 'docker/windows/update_docker_image.ps1.erb' | |||
$update_docker_image_path = 'C:/Windows/Temp/update_docker_image.ps1' | |||
$exec_environment = 'PATH=C:/Program Files/Docker/' | |||
$update_docker_image_path = "${::systemroot}/Temp/update_docker_image.ps1" |
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.
See above. Systemroot\temp is not what you want.
manifests/params.pp
Outdated
$tls_cacert = 'C:/ProgramData/docker/certs.d/ca.pem' | ||
$tls_cert = 'C:/ProgramData/docker/certs.d/server-cert.pem' | ||
$tls_key = 'C:/ProgramData/docker/certs.d/server-key.pem' | ||
$tls_cacert = "${::program_data_path}/docker/certs.d/ca.pem" |
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.
This is configurable for the Docker daemon. Should this path be parameterised?
manifests/registry.pp
Outdated
@@ -48,9 +48,9 @@ | |||
$docker_command = $docker::params::docker_command | |||
|
|||
if $::osfamily == 'windows' { | |||
$exec_environment = ['PATH=C:/Program Files/Docker/'] | |||
$exec_environment = ["PATH=${::program_files_path}/Docker/"] |
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.
Setting PATH and exec_path
is bad practice
https://puppet.com/docs/puppet/5.3/types/exec.html#exec-attribute-environment
lib/facter/docker.rb
Outdated
@@ -67,3 +67,24 @@ def interfaces | |||
end | |||
end | |||
end | |||
|
|||
Facter.add(:systemroot) do |
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'm not keen on these fact names. It's very possible they will collide with other modules that need to do same thing.
Perhaps prefix with docker_
or something?
Also it's generally considered better practice for one file per fact. Although I see prior art says otherwise.
manifests/run.pp
Outdated
$exec_provider = 'powershell' | ||
$cidfile = "c:/Windows/Temp/${service_prefix}${sanitised_title}.cid" | ||
$cidfile = "${::systemroot}/Temp/${service_prefix}${sanitised_title}.cid" |
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.
See above. Systemroot\temp is not what you want.
manifests/services.pp
Outdated
$exec_timeout = 3000 | ||
$exec_path = ['c:/Windows/Temp/', 'C:/Program Files/Docker/'] | ||
$exec_path = ["${::systemroot}/Temp/", "${::program_files_path}/Docker/"] |
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.
See above about PATH= and exec_path
( | ||
[string]$DockerImage | ||
) | ||
$docker_cmd = "${Env:ProgramFiles}\docker\docker.exe" |
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.
Given docker_cmd is part of the params.pp surely we should be using that?
spec/defines/image_windows_spec.rb
Outdated
end | ||
|
||
context 'with ensure => present and image_tag => nanoserver' do | ||
let(:params) { { 'ensure' => 'present', 'image_tag' => 'nanoserver' } } | ||
it { should contain_exec('& C:/Windows/Temp/update_docker_image.ps1 base:nanoserver') } | ||
it { should contain_exec('& C:/Windows/Temp/update_docker_image.ps1 -DockerImage base:nanoserver') } |
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 tests seem very brittle for the resource name. Perhaps a better resource name would make sense?
c95cb9c
to
61748fc
Compare
@glennsarti i've fixed some of the problems. |
@florindragos So you're running your Windows tests under cygwin? |
@glennsarti beaker uses ssh to connect to the hosts running on vmpooler. on windows, cygwin is used for the ssh server |
Seems very odd given a lot of other modules use env vars in acceptance. Have you got some debug logs etc. to show the issue? |
I'm seeing really strange behaviour using TMP env var for the custom fact.
but running the tests: even if we got C:\cygwin64\tmp, this is not the value we are expecting... |
On a real windows machine using PowerShell Note - Ignore the Using
Using
Note that these give different values So given that;
Changing your code because of a flaky test or test environment is bad idea. We know that the correct env var is TMP, and the fact you're working around this is a "bad smell" in the testing framework. |
61748fc
to
73c53ab
Compare
@glennsarti you're right. making assumptions for the temp folder location in the module just so the tests are working is wrong. The temp folder could also be C:\Users\Administrator\AppData\Local\Temp\2 |
docker_path = "/cygdrive/c/Program Files/Docker" | ||
host.add_env_var('PATH', docker_path) | ||
host.add_env_var('TEMP', 'C:\Users\Administrator\AppData\Local\Temp') |
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.
This still seems very wrong. The host should already have a correctly setup TEMP directory.
Even though the cygwin environment says \tmp
, external processes created from within cygwin use C:\cygwin64\tmp
Windows 2012R2 Pooler VM
Administrator@adx7v3xdcx8nwfn ~
$ export
...
declare -x TEMP="/tmp"
declare -x TERM="xterm-256color"
declare -x TMP="/tmp"
...
Administrator@adx7v3xdcx8nwfn ~
$ cmd.exe /c set temp
TEMP=C:\cygwin64\tmp
Administrator@adx7v3xdcx8nwfn ~
$ powershell.exe -Command "Write-Host \$ENV:TEMP"
C:\cygwin64\tmp
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.
That is the way it should work. Even though facter shows the fact pointing to C:\cygwin64\tmp
,
when running tests, the fact does not seem to be initialized:
Warning: Unknown variable: '::docker_user_temp_path'
This happens if I don't set the TEMP env var from within the spec_helper_acceptance...
It works fine for the other 2 facts that are being read from the environment.
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.
It's difficult to understand how overriding a system set env variable is the right way to go, especially since it's being hard coded to a specific user's temp path that may or may not be the correct user for a particular run.
Once this variable is overwritten in this way, it's hard to tell what might be broken down the road. Doesn't it seem like this issue you are seeing might be down to misbehavior on the part of beaker or cygwin, that should be worked around more formally?
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.
Unfortunately, I have not found a way to work around this.
After doing some more digging around, it looks like the user profile is not being loaded when beaker runs the commands.
The commands are being run remote through ssh: ssh Administrator@host -i key cmd /c puppet apply /tmp/manifest
Logging in with ssh will load your user profile and give you the TMP env var but running it remotely will not:
interactive:
ssh [email protected] -i .ssh/id_rsa-acceptance
-bash-4.3$ cmd /c set TMP
TMP=C:\cygwin64\tmp
vs non-interactive:
ssh [email protected] -i .ssh/id_rsa-acceptance cmd /c set TMP
Environment variable TMP not defined
Adding the variable in .ssh/environment
would probably fix this, but we still need to enter the value manually.
I agree, it's not right to hardcode the username but since we are running on the vmpooler VMs, we can assume it is running under Administrator.
lib/facter/docker.rb
Outdated
Facter.add(:docker_user_temp_path) do | ||
confine :osfamily => :windows | ||
setcode do | ||
ENV['TEMP'] |
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.
For the Puppet service this is probably OK. For end users with Unicode characters in their usernames running puppet apply
, there's a chance that this corrupts the directory name due to Ruby bugs.
If you must expose the TEMP directory as a fact (which I would generally advise against if you can help it), you'll want to use the built-in Puppet helpers Puppet::Util.get_env
- see https://github.com/puppetlabs/puppet/blob/24ead48f617cd3912491fe419ac7b67cda53a320/lib/puppet/util.rb#L40-L52
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.
Thanks for the tip. I'll update the code with Puppet::Util.get_env
.
Is there a reason why we should not use expose the TEMP directory as a custom fact and is there a better alternative to getting to the temporary directory from within a manifest?
a7531ab
to
49d485b
Compare
49d485b
to
9c9f3f1
Compare
read windows system paths from custom facts