mirror of
https://github.com/inspec/inspec
synced 2024-11-22 20:53:11 +00:00
pip resource: support non-default pip locations, such as virtualenvs (#2097)
* Update pip resource for #516 allow user to set path to pip executable Signed-off-by: Anthony Shaw <anthonyshaw@apache.org> * support virtualenv path, pip file exec and better logic Signed-off-by: Anthony Shaw <anthonyshaw@apache.org> * add tests for the change to the pip path and resource Signed-off-by: Anthony Shaw <anthonyshaw@apache.org> * tests are case sensitive, although command line is not Signed-off-by: Anthony Shaw <anthonyshaw@apache.org> * use a path verification method instead of a class method Signed-off-by: Anthony Shaw <anthonyshaw@apache.org> * use guard clauses instead of conditionals Signed-off-by: Anthony Shaw <anthonyshaw@apache.org> * change the control flow to return nil when commands are not available Signed-off-by: Anthony Shaw <anthonyshaw@apache.org> * fix the return values when custom pip path is not valid Signed-off-by: Anthony Shaw <anthonyshaw@apache.org> * Refactor pip path detection to fix unit tests Signed-off-by: Adam Leff <adam@leff.co>
This commit is contained in:
parent
d93f623934
commit
d5f33f0b99
5 changed files with 84 additions and 20 deletions
|
@ -7,6 +7,7 @@
|
|||
# it { should be_installed }
|
||||
# end
|
||||
#
|
||||
|
||||
module Inspec::Resources
|
||||
class PipPackage < Inspec.resource(1)
|
||||
name 'pip'
|
||||
|
@ -15,10 +16,17 @@ module Inspec::Resources
|
|||
describe pip('Jinja2') do
|
||||
it { should be_installed }
|
||||
end
|
||||
|
||||
describe pip('django', '/path/to/virtualenv/bin/pip') do
|
||||
it { should be_installed }
|
||||
its('version') { should eq('1.11.4')}
|
||||
end
|
||||
"
|
||||
|
||||
def initialize(package_name)
|
||||
def initialize(package_name, pip_path = nil)
|
||||
@package_name = package_name
|
||||
@pip_cmd = pip_path || default_pip_path
|
||||
return skip_resource 'pip not found' unless inspec.command(@pip_cmd).exist?
|
||||
end
|
||||
|
||||
def info
|
||||
|
@ -26,7 +34,7 @@ module Inspec::Resources
|
|||
|
||||
@info = {}
|
||||
@info[:type] = 'pip'
|
||||
cmd = inspec.command("#{pip_cmd} show #{@package_name}")
|
||||
cmd = inspec.command("#{@pip_cmd} show #{@package_name}")
|
||||
return @info if cmd.exit_status != 0
|
||||
|
||||
params = SimpleConfig.new(
|
||||
|
@ -54,28 +62,28 @@ module Inspec::Resources
|
|||
|
||||
private
|
||||
|
||||
def pip_cmd
|
||||
def default_pip_path
|
||||
return 'pip' unless inspec.os.windows?
|
||||
|
||||
# Pip is not on the default path for Windows, therefore we do some logic
|
||||
# to find the binary on Windows
|
||||
if inspec.os.windows?
|
||||
# we need to detect the pip command on Windows
|
||||
cmd = inspec.command('New-Object -Type PSObject | Add-Member -MemberType NoteProperty -Name Pip -Value (Invoke-Command -ScriptBlock {where.exe pip}) -PassThru | Add-Member -MemberType NoteProperty -Name Python -Value (Invoke-Command -ScriptBlock {where.exe python}) -PassThru | ConvertTo-Json')
|
||||
begin
|
||||
paths = JSON.parse(cmd.stdout)
|
||||
# use pip if it on system path
|
||||
pipcmd = paths['Pip']
|
||||
# calculate path on windows
|
||||
if defined?(paths['Python']) && pipcmd.nil?
|
||||
pipdir = paths['Python'].split('\\')
|
||||
# remove python.exe
|
||||
pipdir.pop
|
||||
pipcmd = pipdir.push('Scripts').push('pip.exe').join('/')
|
||||
end
|
||||
rescue JSON::ParserError => _e
|
||||
return nil
|
||||
cmd = inspec.command('New-Object -Type PSObject | Add-Member -MemberType NoteProperty -Name Pip -Value (Invoke-Command -ScriptBlock {where.exe pip}) -PassThru | Add-Member -MemberType NoteProperty -Name Python -Value (Invoke-Command -ScriptBlock {where.exe python}) -PassThru | ConvertTo-Json')
|
||||
begin
|
||||
paths = JSON.parse(cmd.stdout)
|
||||
# use pip if it on system path
|
||||
pipcmd = paths['Pip']
|
||||
# calculate path on windows
|
||||
if defined?(paths['Python']) && pipcmd.nil?
|
||||
pipdir = paths['Python'].split('\\')
|
||||
# remove python.exe
|
||||
pipdir.pop
|
||||
pipcmd = pipdir.push('Scripts').push('pip.exe').join('/')
|
||||
end
|
||||
rescue JSON::ParserError => _e
|
||||
return nil
|
||||
end
|
||||
pipcmd || 'pip'
|
||||
|
||||
pipcmd
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -204,6 +204,8 @@ class MockLoader
|
|||
'/opt/opscode/embedded/bin/gem list --local -a -q ^knife-backup$' => cmd.call('gem-list-local-a-q-knife-backup'),
|
||||
'npm ls -g --json bower' => cmd.call('npm-ls-g--json-bower'),
|
||||
'pip show jinja2' => cmd.call('pip-show-jinja2'),
|
||||
'pip show django' => cmd.call('pip-show-django'),
|
||||
'/test/path/pip show django' => cmd.call('pip-show-non-standard-django'),
|
||||
"Get-Package -Name 'Mozilla Firefox' | ConvertTo-Json" => cmd.call('get-package-firefox'),
|
||||
"Get-Package -Name 'Ruby 2.1.6-p336-x64' | ConvertTo-Json" => cmd.call('get-package-ruby'),
|
||||
"New-Object -Type PSObject | Add-Member -MemberType NoteProperty -Name Service -Value (Get-Service -Name 'dhcp'| Select-Object -Property Name, DisplayName, Status) -PassThru | Add-Member -MemberType NoteProperty -Name WMI -Value (Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq 'dhcp' -or $_.DisplayName -eq 'dhcp'} | Select-Object -Property StartMode) -PassThru | ConvertTo-Json" => cmd.call('get-service-dhcp'),
|
||||
|
|
33
test/unit/mock/cmd/pip-show-django
Normal file
33
test/unit/mock/cmd/pip-show-django
Normal file
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
Metadata-Version: 2.0
|
||||
Name: Django
|
||||
Version: 1.10.5
|
||||
Summary: A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
|
||||
Home-page: http://www.djangoproject.com/
|
||||
Author: Django Software Foundation
|
||||
Author-email: foundation@djangoproject.com
|
||||
Installer: pip
|
||||
License: BSD
|
||||
Location: /usr/lib/python3.5/site-packages
|
||||
Requires:
|
||||
Classifiers:
|
||||
Development Status :: 5 - Production/Stable
|
||||
Environment :: Web Environment
|
||||
Framework :: Django
|
||||
Intended Audience :: Developers
|
||||
License :: OSI Approved :: BSD License
|
||||
Operating System :: OS Independent
|
||||
Programming Language :: Python
|
||||
Programming Language :: Python :: 2
|
||||
Programming Language :: Python :: 2.7
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3.4
|
||||
Programming Language :: Python :: 3.5
|
||||
Topic :: Internet :: WWW/HTTP
|
||||
Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||
Topic :: Internet :: WWW/HTTP :: WSGI
|
||||
Topic :: Software Development :: Libraries :: Application Frameworks
|
||||
Topic :: Software Development :: Libraries :: Python Modules
|
||||
Entry-points:
|
||||
[console_scripts]
|
||||
django-admin = django.core.management:execute_from_command_line
|
9
test/unit/mock/cmd/pip-show-non-standard-django
Normal file
9
test/unit/mock/cmd/pip-show-non-standard-django
Normal file
|
@ -0,0 +1,9 @@
|
|||
Name: Django
|
||||
Version: 1.11.4
|
||||
Summary: A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
|
||||
Home-page: https://www.djangoproject.com/
|
||||
Author: Django Software Foundation
|
||||
Author-email: foundation@djangoproject.com
|
||||
License: BSD
|
||||
Location: /path/to/site-packages
|
||||
Requires: pytz
|
|
@ -12,4 +12,16 @@ describe 'Inspec::Resources::Pip' do
|
|||
_(resource.installed?).must_equal true
|
||||
_(resource.info).must_equal pkg
|
||||
end
|
||||
it 'verify pip package default parsing' do
|
||||
resource = load_resource('pip', 'django')
|
||||
pkg = {:name=>'Django', :installed=>true, :version=>'1.10.5', :type=>'pip'}
|
||||
_(resource.installed?).must_equal true
|
||||
_(resource.info).must_equal pkg
|
||||
end
|
||||
it 'verify pip package non default parsing' do
|
||||
resource = load_resource('pip', 'django', '/test/path/pip')
|
||||
pkg = {:name=>'Django', :installed=>true, :version=>'1.11.4', :type=>'pip'}
|
||||
_(resource.installed?).must_equal true
|
||||
_(resource.info).must_equal pkg
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue