Skip to content
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

(PUP-11184) Expand to long paths #8768

Merged
merged 2 commits into from
Oct 1, 2021

Conversation

joshcooper
Copy link
Contributor

@joshcooper joshcooper commented Sep 17, 2021

Previously, puppet failed to load if the current working directory was a short
Windows path. This was due to trying to require Puppet::Util::Uniquefile using
its long and short path. This regression was introduced with the move to
require_relative.

The Autoload.files_in_dir method is expected to return relative paths that are
contained within the dir argument. For example, returning an array containing
puppet/provider/exec/posix.

However, if the dir argument contained a short Windows path and the short path
wasn't the last directory component, then the files_in_dir method returned a
relative path of the form, because Dir.glob always returns long paths:

../../../../../../../Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/exec/posix

Later the autoloader joined Puppet[:libdir] and the relative path above,
resulting in a non-canonical path:

C:/ProgramData/PuppetLabs/puppet/cache/lib/../../../../../../../Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/exec/posix.rb

The autoloader then called Kernel.load with the long path:

C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/exec/posix.rb

Which eventually tried to require relatively uniquefile using a long path.
However, that would fail because it had already been required using its 8.3 path:

irb(main):002:0> $LOADED_FEATURES.grep(/\/uniquefile/)
=> ["C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/file_system/uniquefile.rb"]

This issue wasn't an issue prior to require_relative, because we called require 'puppet/util/uniquefile' and ruby knew it had already required that file.

This commit modifies files_in_dir to convert the base dir to a long path, so
that dir is always a prefix for the globbed child.

@joshcooper
Copy link
Contributor Author

joshcooper commented Sep 17, 2021

I need to add an integration test for this using short paths

@joshcooper joshcooper force-pushed the expand_long_path branch 2 times, most recently from c94d415 to 48b58a3 Compare September 24, 2021 20:55
@joshcooper joshcooper marked this pull request as ready for review September 24, 2021 21:01
@joshcooper joshcooper requested review from a team September 24, 2021 21:01
@joshcooper
Copy link
Contributor Author

jenkins please test this on redhat7-64a,windows2019-64a

Dir.glob behaves differently across platforms and ruby versions, don't
stub it.
Previously, puppet failed to load if the current working directory was a short
Windows path. This was due to trying to require `Puppet::Util::Uniquefile` using
its long and short path. This regression was introduced with the move to
require_relative.

The `Autoload.files_in_dir` method is expected to return relative paths that are
contained within the `dir` argument. For example, returning an array containing
`puppet/provider/exec/posix`.

However, if the `dir` argument contained a short Windows path and the short path
wasn't the last directory component, then the `files_in_dir` method returned a
relative path of the form, because `Dir.glob` always returns long paths:

    ../../../../../../../Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/exec/posix

Later the autoloader joined `Puppet[:libdir]` and the relative path above,
resulting in a non-canonical path:

    C:/ProgramData/PuppetLabs/puppet/cache/lib/../../../../../../../Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/exec/posix.rb

The autoloader then called `Kernel.load` with the long path:

    C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/exec/posix.rb

Which eventually tried to require relatively uniquefile using a long path.
However, that would fail because it had already been required using its 8.3 path:

    irb(main):002:0> $LOADED_FEATURES.grep(/\/uniquefile/)
    => ["C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/file_system/uniquefile.rb"]

This issue wasn't an issue prior to require_relative, because we called `require
'puppet/util/uniquefile'` and ruby knew it had already required that file.

This commit modifies `files_in_dir` to convert the base `dir` to a long path, so
that `dir` is always a prefix for the globbed child.
@joshcooper joshcooper requested a review from a team as a code owner September 27, 2021 16:56
@CLAassistant
Copy link

CLAassistant commented Sep 27, 2021

CLA assistant check
All committers have signed the CLA.

@joshcooper joshcooper changed the base branch from 6.x to main September 27, 2021 16:57
@joshcooper
Copy link
Contributor Author

jenkins please test this on redhat7-64a,windows2019-64a

@joshcooper
Copy link
Contributor Author

To verify this fix on Windows:

  1. cmd /c start /w msiexec /qn /i https://downloads.puppetlabs.com/windows/puppet7/puppet-agent-7.11.0-x64.msi
  2. cd C:\PROGRA~1\Puppet~1\Puppet\bin
  3. puppet --version should fail with an exception about Uniquefile
  4. Install puppet-agent from this PR
  5. puppet --version should just print the version number

@joshcooper joshcooper closed this Sep 27, 2021
@joshcooper joshcooper reopened this Sep 27, 2021
@GabrielNagy
Copy link
Contributor

Something went weird here and it seems that Jenkins took your last comment as the test trigger string (probably due to closing/reopening the PR):

02:20:55 ++ jenkins_test_this_from_comment 'To verify this fix on Windows:\r\n\r\n1. `cmd /c start /w msiexec /qn /i https://downloads.puppetlabs.com/windows/puppet7/puppet-agent-7.11.0-x64.msi`\r\n2. `cd C:\PROGRA~1\Puppet~1\Puppet\bin`\r\n3. `puppet --version` should fail with an exception about `Uniquefile`\r\n4. Install puppet-agent from this PR\r\n5. `puppet --version` should just print the version number'

https://jenkins-platform.delivery.puppetlabs.net/job/platform_puppet_puppet-agent-component-prt-prep-project_pr-trigger/1502/console

I'm just gonna kick things off again.

@GabrielNagy
Copy link
Contributor

jenkins please test this on redhat7-64a,windows2019-64a

@GabrielNagy
Copy link
Contributor

GabrielNagy commented Sep 29, 2021

@joshcooper I cannot reproduce this with the method you suggested. I'm getting the following warnings, but no failures:

Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.

C:\Users\Administrator>cmd /c start /w msiexec /qn /i https://downloads.puppetlabs.com/windows/puppet7/puppet-agent-7.11.0-x64.msi

C:\Users\Administrator>cd C:\PROGRA~1\Puppet~1\Puppet\bin

C:\PROGRA~1\PUPPET~1\Puppet\bin>puppet --version
C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/facter/util/file_helper.rb:9: warning: already initialized constant Class::DEBUG_MESSAGE
C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/facter/util/file_helper.rb:9: warning: previous definition of DEBUG_MESSAGE was here
C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/facter/framework/core/options/options_validator.rb:5: warning: already initialized constant Facter::OptionsValidator::INVALID_PAIRS_RULES
C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/facter/framework/core/options/options_validator.rb:5: warning: previous definition of INVALID_PAIRS_RULES was here
C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/facter/framework/core/options/options_validator.rb:15: warning: already initialized constant Facter::OptionsValidator::DUPLICATED_OPTIONS_RULES
C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/facter/framework/core/options/options_validator.rb:15: warning: previous definition of DUPLICATED_OPTIONS_RULES was here
C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/facter/framework/core/options/options_validator.rb:18: warning: already initialized constant Facter::OptionsValidator::LOG_LEVEL
C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/facter/framework/core/options/options_validator.rb:18: warning: previous definition of LOG_LEVEL was here
7.11.0

C:\PROGRA~1\PUPPET~1\Puppet\bin>

Installed the build from this PR and I'm getting the same warnings (this is on a Windows 2012R2 box).

@joshcooper
Copy link
Contributor Author

joshcooper commented Sep 29, 2021

Sorry @GabrielNagy, my bad. You'll have to trigger type/provider loading such as:

C:\PROGRA~1\PUPPET~1\Puppet\bin>puppet resource user
...
Error: Could not autoload ../../../../../../../Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/user/directoryservice: superclass mismatch for class Uniquefile
Error: Could not autoload puppet/type/user: Could not autoload ../../../../../../../Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/user/directoryservice: superclass mismatch for class Uniquefile
Error: Could not run: Could not autoload puppet/type/user: Could not autoload ../../../../../../../Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/user/directoryservice: superclass mismatch for class Uniquefile

With the fix, there are still a few warnings coming from facter due to constant redefinitions, but the command should list users on the system.

@GabrielNagy GabrielNagy merged commit 90ec8bd into puppetlabs:main Oct 1, 2021
@joshcooper joshcooper deleted the expand_long_path branch October 10, 2024 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants