在哈希上的厨师循环中,执行资源插入最后一个条目而不是当前条目
In a chef loop over a hash, execute resource interpolates the last entry instead of current entry
我编写了一个方法来创建多个逻辑卷,作为安装应用程序的设置的一部分。我在配方中有一个哈希值,它是我通过读取 JSON 文件创建的,该文件包含驱动器的所有元数据。
配方循环遍历此哈希,应该首先创建一个逻辑卷,然后立即执行 tune2fs 命令。
现在假设我们处于循环的第一次迭代中。它为散列中的第一个条目 (lv_u01) 创建逻辑卷就好了,但是当它通知执行块时(在同一个循环中,立即),它以某种方式从中插入 key/values哈希中的最后一个条目 (lv_u03)。我已经尝试了多次,它一直在做同样的事情。我进行了搜索,但找不到任何有关它为何这样做的相关信息。这与计时器有关吗?我想在创建逻辑卷后立即 运行 tune2fs 命令,因为稍后在循环中我安装了卷,并且此步骤需要在其他步骤 运行 之前发生。这就是我立即使用的原因。
谁能帮我理解我做错了什么。
这是我看到的错误:
* lvm_logical_volume[lv_u01] action create
* execute[Run tune2fs] action run
================================================================================
Error executing action `run` on resource 'execute[Run tune2fs]'
================================================================================
Mixlib::ShellOut::ShellCommandFailed
------------------------------------
Expected process to exit with [0], but received '1'
---- Begin output of tune2fs -i 0 -c 0 /dev/my_vg/lv_u03 ----
STDOUT: tune2fs 1.45.4 (23-Sep-2019)
STDERR: tune2fs: No such file or directory while trying to open /dev/my_vg/lv_u03
Couldn't find valid filesystem superblock.
---- End output of tune2fs -i 0 -c 0 /dev/my_vg/lv_u03 ----
Ran tune2fs -i 0 -c 0 /dev/my_vg/lv_u03 returned 1
Resource Declaration:
---------------------
# In /tmp/kitchen/cache/cookbooks/cookbook_name/recipes/recipe.rb
88: execute 'Run tune2fs' do
89: command "tune2fs -i 0 -c 0 /dev/#{val_hash['vg_name']}/#{lv_name}"
90: action :nothing
91: end
92:
Compiled Resource:
------------------
# Declared in /tmp/kitchen/cache/cookbooks/cookbook_name/recipes/recipe.rb:88:in `block in from_file'
execute("Run tune2fs") do
action [:nothing]
default_guard_interpreter :execute
command "tune2fs -i 0 -c 0 /dev/my_vg/lv_u03"
backup 5
declared_type :execute
cookbook_name "cookbook_name"
recipe_name "recipe_name"
domain nil
user nil
end
System Info:
------------
chef_version=14.14.25
platform=centos
platform_version=8.2.2004
ruby=ruby 2.5.7p206 (2019-10-01 revision 67816) [x86_64-linux]
program_name=/bin/chef-client
executable=/opt/chef/bin/chef-client
代码如下:
recipe.rb
# Read metadata about drives into a hash
require 'json'
json_file = File.open 'lv_metadata.json'
lv_hash = JSON.load json_file
json_file.close
# Create and format logical volumes.
lv_hash.each do |lv_name, val_hash|
# This resource will create the logical volume based on the parameters available in lv_hash and then format it
# If sizing is static, use the fixed value else use 100% of the free space
lvm_logical_volume lv_name do
group val_hash['vg_name']
size lazy {val_hash['sizing'] == 'static' ? "#{val_hash['disk_sizes'][app_env][vm_size]}G" : "100%FREE"}
filesystem 'ext3'
filesystem_params lazy {lv_name == 'lv_u02' ? "-m 0 -b #{val_hash['block_size']} -J size=256" : "-m 0 -b #{val_hash['block_size']}"}
notifies :run, "execute[Run tune2fs]", :immediately
end
# Runs tune2fs to disable time-dependent checking.
# When setting max-mount-count to 0, the number of times the filesystem is mounted will be disregarded by e2fsck(8) and the kernel.
execute 'Run tune2fs' do
command "tune2fs -i 0 -c 0 /dev/#{val_hash['vg_name']}/#{lv_name}"
action :nothing
end
# Create the directory where the logical volume will be mounted. Give it a
directory "#{val_hash['filesystem_name']}" do
owner val_hash['owner_name']
group val_hash['group_name']
mode val_hash['permissions']
recursive true
action :create
end
# Mount the logical volume at the specified filesystem path and enable it to add entry to fstab.
mount "#{val_hash['filesystem_name']}" do
device "/dev/#{val_hash['vg_name']}/#{lv_name}"
fstype 'ext3'
options val_hash['options']
dump 0
pass 0
action [:mount, :enable]
end
end
lv_metadata.json
{
"lv_u01": {
"vg_name": "vg_username",
"filesystem_name": "/u01",
"owner_name": "username",
"group_name": "groupname",
"permissions": 755,
"options": "defaults",
"sizing": "static",
"disk_sizes": {
"dev": {
"small": 50,
"medium": 50,
"large": 50
},
"qa": {
"small": 100,
"medium": 100,
"large": 100
},
"prod": {
"small": 200,
"medium": 200,
"large": 200
}
},
"block_size": 4096
},
"lv_u02": {
"vg_name": "my_vg",
"filesystem_name": "/u02",
"owner_name": "username",
"group_name": "groupname",
"permissions": 755,
"options": "defaults",
"sizing": "static",
"disk_sizes": {
"dev": {
"small": 5,
"medium": 5,
"large": 5
},
"qa": {
"small": 8,
"medium": 8,
"large": 100
},
"prod": {
"small": 10,
"medium": 10,
"large": 200
}
},
"block_size": 4096
},
"lv_u03": {
"vg_name": "my_vg",
"filesystem_name": "/u03",
"owner_name": "username",
"group_name": "groupname",
"permissions": 755,
"options": "defaults",
"sizing": "free",
"disk_sizes": {
"dev": {
"small": 5,
"medium": 5,
"large": 5
},
"qa": {
"small": 5,
"medium": 5,
"large": 5
},
"prod": {
"small": 5,
"medium": 5,
"large": 5
}
},
"block_size": 1024
}
}
你不应该使用同名的资源,它们实际上做不同的事情。您在资源集合中有 3 个资源最终具有相同的名称:execute 'Run tune2fs'
,但每个资源都在做自己的事情,因为 command "tune2fs -i 0 -c 0 /dev/#{val_hash['vg_name']}/#{lv_name}"
是不同的。
Chef 只是不知道 3 中的哪个资源,您正在通知
notifies :run, "execute[Run tune2fs]", :immediately
为您的执行资源使用不同的名称:
lvm_logical_volume lv_name do
group val_hash['vg_name']
size lazy {val_hash['sizing'] == 'static' ? "#{val_hash['disk_sizes'][app_env][vm_size]}G" : "100%FREE"}
filesystem 'ext3'
filesystem_params lazy {lv_name == 'lv_u02' ? "-m 0 -b #{val_hash['block_size']} -J size=256" : "-m 0 -b #{val_hash['block_size']}"}
notifies :run, "execute[Run tune2fs for #{lv_name}]", :immediately
end
# Runs tune2fs to disable time-dependent checking.
# When setting max-mount-count to 0, the number of times the filesystem is mounted will be disregarded by e2fsck(8) and the kernel.
execute "Run tune2fs for #{lv_name}" do
command "tune2fs -i 0 -c 0 /dev/#{val_hash['vg_name']}/#{lv_name}"
action :nothing
end
我编写了一个方法来创建多个逻辑卷,作为安装应用程序的设置的一部分。我在配方中有一个哈希值,它是我通过读取 JSON 文件创建的,该文件包含驱动器的所有元数据。
配方循环遍历此哈希,应该首先创建一个逻辑卷,然后立即执行 tune2fs 命令。
现在假设我们处于循环的第一次迭代中。它为散列中的第一个条目 (lv_u01) 创建逻辑卷就好了,但是当它通知执行块时(在同一个循环中,立即),它以某种方式从中插入 key/values哈希中的最后一个条目 (lv_u03)。我已经尝试了多次,它一直在做同样的事情。我进行了搜索,但找不到任何有关它为何这样做的相关信息。这与计时器有关吗?我想在创建逻辑卷后立即 运行 tune2fs 命令,因为稍后在循环中我安装了卷,并且此步骤需要在其他步骤 运行 之前发生。这就是我立即使用的原因。
谁能帮我理解我做错了什么。
这是我看到的错误:
* lvm_logical_volume[lv_u01] action create
* execute[Run tune2fs] action run
================================================================================
Error executing action `run` on resource 'execute[Run tune2fs]'
================================================================================
Mixlib::ShellOut::ShellCommandFailed
------------------------------------
Expected process to exit with [0], but received '1'
---- Begin output of tune2fs -i 0 -c 0 /dev/my_vg/lv_u03 ----
STDOUT: tune2fs 1.45.4 (23-Sep-2019)
STDERR: tune2fs: No such file or directory while trying to open /dev/my_vg/lv_u03
Couldn't find valid filesystem superblock.
---- End output of tune2fs -i 0 -c 0 /dev/my_vg/lv_u03 ----
Ran tune2fs -i 0 -c 0 /dev/my_vg/lv_u03 returned 1
Resource Declaration:
---------------------
# In /tmp/kitchen/cache/cookbooks/cookbook_name/recipes/recipe.rb
88: execute 'Run tune2fs' do
89: command "tune2fs -i 0 -c 0 /dev/#{val_hash['vg_name']}/#{lv_name}"
90: action :nothing
91: end
92:
Compiled Resource:
------------------
# Declared in /tmp/kitchen/cache/cookbooks/cookbook_name/recipes/recipe.rb:88:in `block in from_file'
execute("Run tune2fs") do
action [:nothing]
default_guard_interpreter :execute
command "tune2fs -i 0 -c 0 /dev/my_vg/lv_u03"
backup 5
declared_type :execute
cookbook_name "cookbook_name"
recipe_name "recipe_name"
domain nil
user nil
end
System Info:
------------
chef_version=14.14.25
platform=centos
platform_version=8.2.2004
ruby=ruby 2.5.7p206 (2019-10-01 revision 67816) [x86_64-linux]
program_name=/bin/chef-client
executable=/opt/chef/bin/chef-client
代码如下:
recipe.rb
# Read metadata about drives into a hash
require 'json'
json_file = File.open 'lv_metadata.json'
lv_hash = JSON.load json_file
json_file.close
# Create and format logical volumes.
lv_hash.each do |lv_name, val_hash|
# This resource will create the logical volume based on the parameters available in lv_hash and then format it
# If sizing is static, use the fixed value else use 100% of the free space
lvm_logical_volume lv_name do
group val_hash['vg_name']
size lazy {val_hash['sizing'] == 'static' ? "#{val_hash['disk_sizes'][app_env][vm_size]}G" : "100%FREE"}
filesystem 'ext3'
filesystem_params lazy {lv_name == 'lv_u02' ? "-m 0 -b #{val_hash['block_size']} -J size=256" : "-m 0 -b #{val_hash['block_size']}"}
notifies :run, "execute[Run tune2fs]", :immediately
end
# Runs tune2fs to disable time-dependent checking.
# When setting max-mount-count to 0, the number of times the filesystem is mounted will be disregarded by e2fsck(8) and the kernel.
execute 'Run tune2fs' do
command "tune2fs -i 0 -c 0 /dev/#{val_hash['vg_name']}/#{lv_name}"
action :nothing
end
# Create the directory where the logical volume will be mounted. Give it a
directory "#{val_hash['filesystem_name']}" do
owner val_hash['owner_name']
group val_hash['group_name']
mode val_hash['permissions']
recursive true
action :create
end
# Mount the logical volume at the specified filesystem path and enable it to add entry to fstab.
mount "#{val_hash['filesystem_name']}" do
device "/dev/#{val_hash['vg_name']}/#{lv_name}"
fstype 'ext3'
options val_hash['options']
dump 0
pass 0
action [:mount, :enable]
end
end
lv_metadata.json
{
"lv_u01": {
"vg_name": "vg_username",
"filesystem_name": "/u01",
"owner_name": "username",
"group_name": "groupname",
"permissions": 755,
"options": "defaults",
"sizing": "static",
"disk_sizes": {
"dev": {
"small": 50,
"medium": 50,
"large": 50
},
"qa": {
"small": 100,
"medium": 100,
"large": 100
},
"prod": {
"small": 200,
"medium": 200,
"large": 200
}
},
"block_size": 4096
},
"lv_u02": {
"vg_name": "my_vg",
"filesystem_name": "/u02",
"owner_name": "username",
"group_name": "groupname",
"permissions": 755,
"options": "defaults",
"sizing": "static",
"disk_sizes": {
"dev": {
"small": 5,
"medium": 5,
"large": 5
},
"qa": {
"small": 8,
"medium": 8,
"large": 100
},
"prod": {
"small": 10,
"medium": 10,
"large": 200
}
},
"block_size": 4096
},
"lv_u03": {
"vg_name": "my_vg",
"filesystem_name": "/u03",
"owner_name": "username",
"group_name": "groupname",
"permissions": 755,
"options": "defaults",
"sizing": "free",
"disk_sizes": {
"dev": {
"small": 5,
"medium": 5,
"large": 5
},
"qa": {
"small": 5,
"medium": 5,
"large": 5
},
"prod": {
"small": 5,
"medium": 5,
"large": 5
}
},
"block_size": 1024
}
}
你不应该使用同名的资源,它们实际上做不同的事情。您在资源集合中有 3 个资源最终具有相同的名称:execute 'Run tune2fs'
,但每个资源都在做自己的事情,因为 command "tune2fs -i 0 -c 0 /dev/#{val_hash['vg_name']}/#{lv_name}"
是不同的。
Chef 只是不知道 3 中的哪个资源,您正在通知
notifies :run, "execute[Run tune2fs]", :immediately
为您的执行资源使用不同的名称:
lvm_logical_volume lv_name do
group val_hash['vg_name']
size lazy {val_hash['sizing'] == 'static' ? "#{val_hash['disk_sizes'][app_env][vm_size]}G" : "100%FREE"}
filesystem 'ext3'
filesystem_params lazy {lv_name == 'lv_u02' ? "-m 0 -b #{val_hash['block_size']} -J size=256" : "-m 0 -b #{val_hash['block_size']}"}
notifies :run, "execute[Run tune2fs for #{lv_name}]", :immediately
end
# Runs tune2fs to disable time-dependent checking.
# When setting max-mount-count to 0, the number of times the filesystem is mounted will be disregarded by e2fsck(8) and the kernel.
execute "Run tune2fs for #{lv_name}" do
command "tune2fs -i 0 -c 0 /dev/#{val_hash['vg_name']}/#{lv_name}"
action :nothing
end