我正在尝试实现一个系统,因为应用程序需要跨多个节点使用相同的用户ID,我们在一个小的mysql表上查找,该表具有存储在autoincrememnting表中的应用程序名称和相应的ID。如果用户ID尚不存在,我们创建它然后返回它。由于我在“数据库”菜谱中遇到的问题,我决定在bash脚本中实现Mysql查询,该脚本将UID返回给Stdout并让Chef在用户创建中使用它。作为Mysql脚本的参数,我们为我们发布的apllication名称提供node属性,这是在DB中搜索的条目。
我遇到的问题是我试图通过ruby_block设置变量,这似乎没有被处理。 Chef日志显示该变量未被设置,当我从方程中完全删除了mysql脚本时,它仍然没有被设置。据我所知,它的语法相当简单,所以可以看出为什么会失败。这是代码:
define :create_application_ids do
# Assign variable names to the parameters passed.
application = params[:application_name]
# Set the fail flag to zero.
node.default[:deploy][application][:fail] = 0
# Deploy our mysql query script to get (or create, if required) a user ID for the application
template "query_mysql.bash" do
path "/root/query_mysql.bash"
source "query_mysql.bash.erb"
owner "root"
group "root"
mode "0750"
end
ruby_block "set_app_id" do
block do
id = `/root/query_mysql.bash #{node[:deploy][application]}`
end
action :create
end
Chef::Log.info "MY-DEPLOY: The ID variable is #{id}"
# If a user and group ID has been specified in the JSON string for the
# application, then create them both.
if (defined?(id))
directory node[:deploy][application][:home_dir] do
owner "root"
group "root"
mode 0777
recursive true
action :create
end
group "#{node[:deploy][application][:group_name]}" do
gid id
only_if { `cat /etc/group | grep -E '^#{node[:deploy][application][:group_name]}:'` }
end
user "#{node[:deploy][application][:user_name]}" do
uid id
gid node[:deploy][application][:group_name]
home "#{node[:deploy][application][:home_dir]}"
shell "/sbin/nologin"
only_if { `cat /etc/passwd | grep -E '^#{node[:deploy][application][:user_name]}:'` }
end
# Create any standard directories for the user.
create_application_dirs do
application_name application
end
else
Chef::Log.info "MY: #{node[:deploy][application]}"
# Since this failed, set the fail flag to 1.
node.default[:deploy][application][:fail] = 1
log "message" do
message "MY-DEPLOY: Cannot deploy application without unique user and group ID"
level :fatal
end
end
end
我在Chef输出中看到了这个:
Recipe Compile Error in /var/lib/aws/opsworks/cache.stage2/cookbooks/my-deploy/recipes/repository.rb
================================================================================
NameError
---------
No resource, method, or local variable named `id' for `Chef::Recipe "repository"'
Cookbook Trace:
---------------
/var/lib/aws/opsworks/cache.stage2/cookbooks/my-deploy/definitions/create_application_ids.rb:25:in `block in from_file'
/var/lib/aws/opsworks/cache.stage2/cookbooks/my-deploy/recipes/repository.rb:15:in `block in from_file'
/var/lib/aws/opsworks/cache.stage2/cookbooks/my-deploy/recipes/repository.rb:2:in `each'
/var/lib/aws/opsworks/cache.stage2/cookbooks/my-deploy/recipes/repository.rb:2:in `from_file'
Relevant File Content:
----------------------
/var/lib/aws/opsworks/cache.stage2/cookbooks/my-deploy/definitions/create_application_ids.rb:
18: ruby_block "set_app_id" do
19: block do
20: id = `/root/query_mysql.bash #{node[:deploy][application]}`
21: end
22: action :create
23: end
24:
25>> Chef::Log.info "MY-DEPLOY: The ID variable is #{id}"
26:
27: # If a user and group ID has been specified in the JSON string for the
28: # application, then create them both.
29:
30: if (defined?(id))
31: directory node[:deploy][application][:home_dir] do
32: owner "root"
33: group "root"
34: mode 0777
[2014-10-08T00:55:49+11:00] ERROR: Running exception handlers
[2014-10-08T00:55:49+11:00] ERROR: Exception handlers complete
[2014-10-08T00:55:49+11:00] FATAL: Stacktrace dumped to /var/lib/aws/opsworks/cache.stage2/chef-stacktrace.out
[2014-10-08T00:55:50+11:00] ERROR: No resource, method, or local variable named `id' for `Chef::Recipe "repository"'
[2014-10-08T00:55:50+11:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)
答案 0 :(得分:2)
你正在遇到厨师跑步问题的两个阶段。请参阅documentation about it here
首先通过编译食谱/定义并制作资源的“堆栈”。
Lwrp可以通过在使用正确的参数调用资源(在收敛时间)进行评估来解决您的问题。
在此评估您的定义,创建一个类型为ruby_block
的资源,该资源将在收敛时执行。
在定义此资源之后,您测试是否定义了id
,但此时尚未运行ruby_block。
您必须更改代码,剥离if (defined?(id))
。
您在下面使用的资源已经是幂等的(不需要用户和组资源中的only_if
)。
但是,您必须在thoose资源中使用id的延迟评估,以避免使用nil定义它们来代替您的id。
即
group "#{node[:deploy][application][:group_name]}" do
gid lazy { id }
only_if { `cat /etc/group | grep -E '^#{node[:deploy][application][:group_name]}:'` }
end
如果您确实想要捕获错误并打印自定义消息,则可以使用开始/救援块,因为具有nil id的组或用户资源会引发异常IIRC。
答案 1 :(得分:1)
Tensibai的答案非常好,我建议你接受它。也就是说,我的个人风格是采取略微不同的方法。
Chef-server的一大好处是能够搜索。因此,我会将id放在node属性中,而不是独立属性,然后将其与lazy evaluation一起使用。
define :create_application_ids do
# Assign variable names to the parameters passed.
application = params[:application_name]
# Set the fail flag to zero.
node.default[:deploy][application][:fail] = 0
# Deploy our mysql query script to get (or create, if required) a user ID for the application
template "query_mysql.bash" do
path "/root/query_mysql.bash"
source "query_mysql.bash.erb"
owner "root"
group "root"
mode "0750"
end
ruby_block "set_app_id" do
block do
node[application][:id] = `/root/query_mysql.bash #{node[:deploy][application]}`
end
action :create
not_if node[application] && node[application][:id]
end
Chef::Log.info "MY-DEPLOY: The ID variable is #{id}"
# If a user and group ID has been specified in the JSON string for the
# application, then create them both.
directory node[:deploy][application][:home_dir] do
owner "root"
group "root"
mode 0777
recursive true
action :create
end
group "#{node[:deploy][application][:group_name]}" do
gid lazy{ node[application][:id] }
only_if { `cat /etc/group | grep -E '^#{node[:deploy][application][:group_name]}:'` }
end
user "#{node[:deploy][application][:user_name]}" do
uid lazy { node[application][:id] }
gid node[:deploy][application][:group_name]
home "#{node[:deploy][application][:home_dir]}"
shell "/sbin/nologin"
only_if { `cat /etc/passwd | grep -E '^#{node[:deploy][application][:user_name]}:'` }
end
# Create any standard directories for the user.
create_application_dirs do
application_name application
end
end