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

Make send_file aware of user option #277

Merged
merged 6 commits into from
Jan 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions lib/itamae/backend.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,23 @@ def receive_file(src, dst = nil)
@backend.receive_file(src, dst)
end

def send_file(src, dst)
def send_file(src, dst, user: nil)
Itamae.logger.debug "Sending a file from '#{src}' to '#{dst}'..."
unless ::File.exist?(src)
raise SourceNotExistError, "The file '#{src}' doesn't exist."
end
unless ::File.file?(src)
raise SourceNotExistError, "'#{src}' is not a file."
end
@backend.send_file(src, dst)

if self.instance_of?(Backend::Local)
read_command = build_command("cat #{src.shellescape}", {})
write_command = build_command("cat > #{dst.shellescape}", user: user)
command = [read_command, write_command].join(' | ')
run_command(command)
else
@backend.send_file(src, dst)
end
end

def send_directory(src, dst)
Expand Down
4 changes: 2 additions & 2 deletions lib/itamae/resource/file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,12 @@ def send_tempfile

if backend.is_a?(Itamae::Backend::Docker)
run_command(["mkdir", @temppath])
backend.send_file(src, @temppath)
backend.send_file(src, @temppath, user: attributes.user)
@temppath = ::File.join(@temppath, ::File.basename(src))
else
run_command(["touch", @temppath])
run_specinfra(:change_file_mode, @temppath, '0600')
backend.send_file(src, @temppath)
backend.send_file(src, @temppath, user: attributes.user)
end

run_specinfra(:change_file_mode, @temppath, '0600')
Expand Down
6 changes: 6 additions & 0 deletions spec/integration/local_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
describe file('/tmp/file_as_ordinary_user') do
it { should be_file }
it { should be_owned_by "itamae" }
it { should be_grouped_into "itamae" }
end

108 changes: 108 additions & 0 deletions spec/integration/ordinary_user_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
require 'spec_helper'

describe file('/tmp/remote_file') do
it { should be_file }
it { should be_owned_by "ordinary_san" }
it { should be_grouped_into "ordinary_san" }
its(:content) { should match(/Hello Itamae/) }
end

describe file('/tmp/remote_file_root') do
it { should be_file }
it { should be_owned_by "root" }
it { should be_grouped_into "root" }
its(:content) { should match(/Hello Itamae/) }
end

%w[/tmp/remote_file_another_ordinary /tmp/remote_file_another_ordinary_with_root].each do |path|
describe file(path) do
it { should be_file }
it { should be_owned_by "itamae" }
it { should be_grouped_into "itamae" }
its(:content) { should match(/Hello Itamae/) }
end
end

###

describe file('/tmp/file') do
it { should be_file }
it { should be_owned_by "ordinary_san" }
it { should be_grouped_into "ordinary_san" }
its(:content) { should match(/Hello World/) }
end

describe file('/tmp/file_root') do
it { should be_file }
it { should be_owned_by "root" }
it { should be_grouped_into "root" }
its(:content) { should match(/Hello World/) }
end

%w[/tmp/file_another_ordinary /tmp/file_another_ordinary_with_root].each do |path|
describe file(path) do
it { should be_file }
it { should be_owned_by "itamae" }
it { should be_grouped_into "itamae" }
its(:content) { should match(/Hello World/) }
end
end

###

describe file('/tmp/template') do
it { should be_file }
it { should be_owned_by "ordinary_san" }
it { should be_grouped_into "ordinary_san" }
its(:content) { should match(/Hello/) }
its(:content) { should match(/Good bye/) }
its(:content) { should match(/^total memory: \d+kB$/) }
its(:content) { should match(/^uninitialized node key: $/) }
end

describe file('/tmp/template_root') do
it { should be_file }
it { should be_owned_by "root" }
it { should be_grouped_into "root" }
its(:content) { should match(/Hello/) }
its(:content) { should match(/Good bye/) }
its(:content) { should match(/^total memory: \d+kB$/) }
its(:content) { should match(/^uninitialized node key: $/) }
end

%w[/tmp/template_another_ordinary /tmp/template_another_ordinary_with_root].each do |path|
describe file(path) do
it { should be_file }
it { should be_owned_by "itamae" }
it { should be_grouped_into "itamae" }
its(:content) { should match(/Hello/) }
its(:content) { should match(/Good bye/) }
its(:content) { should match(/^total memory: \d+kB$/) }
its(:content) { should match(/^uninitialized node key: $/) }
end
end

###

describe file('/tmp/http_request.html') do
it { should be_file }
it { should be_owned_by "ordinary_san" }
it { should be_grouped_into "ordinary_san" }
its(:content) { should match(/"from":\s*"itamae"/) }
end

describe file('/tmp/http_request_root.html') do
it { should be_file }
it { should be_owned_by "root" }
it { should be_grouped_into "root" }
its(:content) { should match(/"from":\s*"itamae"/) }
end

%w[/tmp/http_request_another_ordinary.html /tmp/http_request_another_ordinary_with_root.html].each do |path|
describe file(path) do
it { should be_file }
it { should be_owned_by "itamae" }
it { should be_grouped_into "itamae" }
its(:content) { should match(/"from":\s*"itamae"/) }
end
end
11 changes: 11 additions & 0 deletions spec/integration/recipes/local.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,14 @@
version '2.0.0'
options ['--no-document']
end

######

# Docker backend raises an error with `user` option, so it tests only on `itamae local`.
# After fix this error, please move this code and the spec to `default.rb`.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried to add the following code to recipes/default.rb, but it does not work.
Because docker backend raises an error with this code.
Docker backend's send_file sends a file with the root user, and currently, it is not configurable, unfortunately.
I guess we can move the code to recipes/default.rb by fixing docker backend, but this pull request does not focus this problem. I guess this problem already exists before this pull request because I do not touch docker backend in this pull request.

file "/tmp/file_as_ordinary_user" do
content "Hello World"
user "itamae"
owner "itamae"
group "itamae"
end
109 changes: 109 additions & 0 deletions spec/integration/recipes/ordinary_user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
remote_file "/tmp/remote_file" do
source "hello.txt"
end

remote_file "/tmp/remote_file_root" do
user 'root'
owner 'root'
group 'root'
source "hello.txt"
end

remote_file "/tmp/remote_file_another_ordinary" do
user 'itamae'
owner 'itamae'
group 'itamae'
source "hello.txt"
end

remote_file "/tmp/remote_file_another_ordinary_with_root" do
user 'root'
owner 'itamae'
group 'itamae'
source "hello.txt"
end

###

file "/tmp/file" do
content "Hello World"
end

file "/tmp/file_root" do
user 'root'
owner 'root'
group 'root'
content 'Hello World'
end

file "/tmp/file_another_ordinary" do
user 'itamae'
owner 'itamae'
group 'itamae'
content 'Hello World'
end

file "/tmp/file_another_ordinary_with_root" do
user 'root'
owner 'itamae'
group 'itamae'
content 'Hello World'
end

###

template "/tmp/template" do
source "hello.erb"
variables goodbye: "Good bye"
end

template "/tmp/template_root" do
user 'root'
owner 'root'
group 'root'
source "hello.erb"
variables goodbye: "Good bye"
end

template "/tmp/template_another_ordinary" do
user 'itamae'
owner 'itamae'
group 'itamae'
source "hello.erb"
variables goodbye: "Good bye"
end

template "/tmp/template_another_ordinary_with_root" do
user 'root'
owner 'itamae'
group 'itamae'
source "hello.erb"
variables goodbye: "Good bye"
end

###

http_request "/tmp/http_request.html" do
url "https://httpbin.org/get?from=itamae"
end

http_request "/tmp/http_request_root.html" do
user 'root'
owner 'root'
group 'root'
url "https://httpbin.org/get?from=itamae"
end

http_request "/tmp/http_request_another_ordinary.html" do
user 'itamae'
owner 'itamae'
group 'itamae'
url "https://httpbin.org/get?from=itamae"
end

http_request "/tmp/http_request_another_ordinary_with_root.html" do
user 'root'
owner 'itamae'
group 'itamae'
url "https://httpbin.org/get?from=itamae"
end
77 changes: 59 additions & 18 deletions tasks/integration_local_spec.rb
Original file line number Diff line number Diff line change
@@ -1,37 +1,76 @@
desc 'Run integration test on `itamae local` command'
task 'spec:integration:local' do
next if RUBY_DESCRIPTION.include?('dev')
desc 'Run all integration tests on `itamae local` command'
task 'spec:integration:local' => ['spec:integration:local:main', 'spec:integration:local:ordinary_user']

IntegrationLocalSpecRunner.new(
[
namespace 'spec:integration:local' do
desc 'Run main integration test with `itamae local`'
task 'main' do
if RUBY_DESCRIPTION.include?('dev')
$stderr.puts "This integration test is skipped with unreleased Ruby."
$stderr.puts "Use released Ruby to execute this integration test."
next
end

IntegrationLocalSpecRunner.new(
[
"spec/integration/recipes/default.rb",
"spec/integration/recipes/default2.rb",
"spec/integration/recipes/redefine.rb",
"spec/integration/recipes/local.rb",
[
"spec/integration/recipes/default.rb",
"spec/integration/recipes/default2.rb",
"spec/integration/recipes/redefine.rb",
"spec/integration/recipes/local.rb",
],
[
"--dry-run",
"spec/integration/recipes/dry_run.rb",
],
],
['spec/integration/default_spec.rb']
).run

end

desc 'Run integration test for ordinary user with `itamae local`'
task 'ordinary_user' do
if RUBY_DESCRIPTION.include?('dev')
$stderr.puts "This integration test is skipped with unreleased Ruby."
$stderr.puts "Use released Ruby to execute this integration test."
next
end

runner = IntegrationLocalSpecRunner.new(
[
"--dry-run",
"spec/integration/recipes/dry_run.rb",
[
"--dry-run",
"spec/integration/recipes/ordinary_user.rb",
],
[
"spec/integration/recipes/ordinary_user.rb"
],
],
],
['spec/integration/default_spec.rb']
).run
['spec/integration/ordinary_user_spec.rb'],
user: 'ordinary_san'
)
runner.docker_exec 'useradd', 'ordinary_san', '-p', '*'
runner.docker_exec 'useradd', 'itamae', '-p', '*', '--create-home'
runner.docker_exec 'sh', '-c', 'echo "ordinary_san ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers'
runner.run
end
end

class IntegrationLocalSpecRunner
CONTAINER_NAME = 'itamae'
include FileUtils

def initialize(suites, specs, ruby_version: RUBY_VERSION.split('.')[0..1].join('.'))
def initialize(suites, specs, ruby_version: RUBY_VERSION.split('.')[0..1].join('.'), user: nil)
@suites = suites
@specs = specs
@ruby_version = ruby_version
end
@user = user

def run
docker_run
prepare
end

def run
provision
serverspec
clean_docker_container
Expand All @@ -57,7 +96,9 @@ def provision
cmd << "-j" << "spec/integration/recipes/node.json"
cmd += suite

docker_exec(*cmd, options: %w[--workdir /itamae])
options = %w[--workdir /itamae]
options.push('--user', @user) if @user
docker_exec(*cmd, options: options)
end
end

Expand Down