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

Login shell #149

Merged
merged 10 commits into from
Sep 20, 2016
2 changes: 2 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,5 @@ Style/SpaceAroundOperators:
Enabled: false
Style/IfUnlessModifier:
Enabled: false
Style/FrozenStringLiteralComment:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we changing the default setting?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's because we don't yet have frozen string literal comments in our files:
http://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Style/FrozenStringLiteralComment

I think it's ok to disable for now and let's tackle this in a rubocop cleanup session 😄

Enabled: false
29 changes: 22 additions & 7 deletions lib/train/extras/command_wrapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class LinuxCommand < CommandWrapperBase
Train::Options.attach(self)

option :sudo, default: false
option :shell, default: false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its a little bit sub-optimal to switch types of a variable, I would prefer nil here, which would lead to the default

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also lets add a comment to give users an idea of potential values

option :login, default: false
option :sudo_options, default: nil
option :sudo_password, default: nil
option :sudo_command, default: nil
Expand All @@ -39,11 +41,12 @@ def initialize(backend, options)
validate_options(options)

@sudo = options[:sudo]
@shell = options[:shell]
@login = options[:login]
@sudo_options = options[:sudo_options]
@sudo_password = options[:sudo_password]
@sudo_command = options[:sudo_command]
@user = options[:user]
@prefix = build_prefix
end

# (see CommandWrapperBase::verify)
Expand Down Expand Up @@ -71,18 +74,22 @@ def verify

# (see CommandWrapperBase::run)
def run(command)
@prefix + command
shell_wrap(sudo_wrap(command))
end

def self.active?(options)
options.is_a?(Hash) && options[:sudo]
options.is_a?(Hash) && (
options[:sudo] ||
options[:shell] ||
options[:login]
)
end

private

def build_prefix
return '' unless @sudo
return '' if @user == 'root'
def sudo_wrap(cmd)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets add comments what these function do

return cmd unless @sudo
return cmd if @user == 'root'

res = (@sudo_command || 'sudo') + ' '

Expand All @@ -93,7 +100,15 @@ def build_prefix

res << @sudo_options.to_s + ' ' unless @sudo_options.nil?

res
res + cmd
end

def shell_wrap(cmd)
return cmd unless @shell || @login
login_param = '--login ' if @login
shell = @shell.instance_of?(String) ? @shell : '$SHELL'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer not to check for the type here


"#{shell} #{login_param}<<< \"#{cmd}\""
end
end

Expand Down
109 changes: 74 additions & 35 deletions test/unit/extras/command_wrapper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,47 +16,86 @@
backend
}

it 'wraps commands in sudo' do
lc = cls.new(backend, { sudo: true })
lc.run(cmd).must_equal "sudo #{cmd}"
end
describe 'sudo wrapping' do
it 'wraps commands in sudo' do
lc = cls.new(backend, { sudo: true })
lc.run(cmd).must_equal "sudo #{cmd}"
end

it 'doesnt wrap commands in sudo if user == root' do
lc = cls.new(backend, { sudo: true, user: 'root' })
lc.run(cmd).must_equal cmd
end
it 'doesnt wrap commands in sudo if user == root' do
lc = cls.new(backend, { sudo: true, user: 'root' })
lc.run(cmd).must_equal cmd
end

it 'wraps commands in sudo with all options' do
opts = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_options: opts })
lc.run(cmd).must_equal "sudo #{opts} #{cmd}"
end
it 'wraps commands in sudo with all options' do
opts = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_options: opts })
lc.run(cmd).must_equal "sudo #{opts} #{cmd}"
end

it 'runs commands in sudo with password' do
pw = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_password: pw })
bpw = Base64.strict_encode64(pw + "\n")
lc.run(cmd).must_equal "echo #{bpw} | base64 --decode | sudo -S #{cmd}"
end
it 'runs commands in sudo with password' do
pw = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_password: pw })
bpw = Base64.strict_encode64(pw + "\n")
lc.run(cmd).must_equal "echo #{bpw} | base64 --decode | sudo -S #{cmd}"
end

it 'wraps commands in sudo_command instead of sudo' do
sudo_command = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_command: sudo_command })
lc.run(cmd).must_equal "#{sudo_command} #{cmd}"
end
it 'wraps commands in sudo_command instead of sudo' do
sudo_command = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_command: sudo_command })
lc.run(cmd).must_equal "#{sudo_command} #{cmd}"
end

it 'wraps commands in sudo_command with all options' do
opts = rand.to_s
sudo_command = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_command: sudo_command, sudo_options: opts })
lc.run(cmd).must_equal "#{sudo_command} #{opts} #{cmd}"
end

it 'wraps commands in sudo_command with all options' do
opts = rand.to_s
sudo_command = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_command: sudo_command, sudo_options: opts })
lc.run(cmd).must_equal "#{sudo_command} #{opts} #{cmd}"
it 'runs commands in sudo_command with password' do
pw = rand.to_s
sudo_command = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_command: sudo_command, sudo_password: pw })
bpw = Base64.strict_encode64(pw + "\n")
lc.run(cmd).must_equal "echo #{bpw} | base64 --decode | #{sudo_command} -S #{cmd}"
end
end

it 'runs commands in sudo_command with password' do
pw = rand.to_s
sudo_command = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_command: sudo_command, sudo_password: pw })
bpw = Base64.strict_encode64(pw + "\n")
lc.run(cmd).must_equal "echo #{bpw} | base64 --decode | #{sudo_command} -S #{cmd}"
describe 'shell wrapping' do
it 'wraps commands in a default shell with login' do
lc = cls.new(backend, { login: true })
lc.run(cmd).must_equal "$SHELL --login <<< \"#{cmd}\""
end

it 'wraps sudo commands in a default shell with login' do
lc = cls.new(backend, { sudo: true, login: true })
lc.run(cmd).must_equal "$SHELL --login <<< \"sudo #{cmd}\""
end

it 'wraps commands in a default shell when shell is true' do
lc = cls.new(backend, { shell: true })
lc.run(cmd).must_equal "$SHELL <<< \"#{cmd}\""
end

it 'doesnt wrap commands in a shell when shell is false' do
lc = cls.new(backend, { shell: false })
lc.run(cmd).must_equal cmd
end

it 'wraps commands in a shell when shell is false, but login is true' do
lc = cls.new(backend, { shell: false, login: true })
lc.run(cmd).must_equal "$SHELL --login <<< \"#{cmd}\""
end

it 'wraps commands in a `shell` instead of default shell' do
lc = cls.new(backend, { shell: '/bin/bash' })
lc.run(cmd).must_equal "/bin/bash <<< \"#{cmd}\""
end

it 'wraps commands in a default shell with login' do
lc = cls.new(backend, { shell: '/bin/bash', login: true })
lc.run(cmd).must_equal "/bin/bash --login <<< \"#{cmd}\""
end
end
end