如何搭建Chef 本地开发环境

时间:2022-03-16 11:44:47

本文简单阐述一下如何在本地搭建一个Chef( Chef是什么? )的开发环境。

想达到的效果

  1. 开发的过程一定是尝试、失败、回滚的过程,快照功能必不可少
  2. 使用chef-solo运行,直接使用开发代码,而不必将代码提交到chef server。连chef-solo的配置都应该是本地的。
  3. 不必进入到虚拟机去触发测试,这样不方便,要支持本地一条命令就触发测试
  4. 这个方案要支持多种操作系统

思路

  1. 命令:使用 rake
  2. 远程触发:使用Telnet.可以跨平台
  3. 访问本地代码:使用VirtualBox的shared folder
  4. 快照功能: 使用VirtualBox的快照功能

方案

结构图如下:

如何搭建Chef 本地开发环境

  1. Test VM需要安装chef-client和Telnet Server.
  2. 开发目录如下
  3. 如何搭建Chef 本地开发环境
  4. 将当前开发目录设置成VirtualBox的shared folder
  5. Telnet上VM,使用net use(windows)或mount 挂载shared folder
  6. 还是Telnet,触发chef-solo。假设挂载到z:盘,那么运行
    chef-solo -c z:/config/test_solo.rb -j z:/conifg/test_node

当然,以上的后4步一定是自动完成。因为chef代码是ruby写的,当然很自然,我们可以使用rake来开发这些命令。这是我开发的一些Task

rake check_cookbook[cookbook_name]   # Check cookbook syntax in local
rake create_cookbook[cookbook_name] # Create new cookbook
in local
rake delete_snapshot[name] # Vbox snapshot delete
rake down # Vm poweroff
rake list_snapshots # Vbox snapshot list
rake restore_snapshot[name] # Vbox snapshot restore
rake restore_to[snapshot_name] # Restore specific snapshot,start
rake take_snapshot[name] # Vbox snapshot take
rake test # Test cookbook.
rake test_from[snapshot_name] # Restore specific snapshot,start and ...
rake up # Vm start

关键步骤实现

虚拟机管理-快照恢复

desc "Restore specific snapshot,start"
task :restore_to,:snapshot_name do
|t,args|
Rake::Task[
"down"].invoke
Rake::Task[
"restore_snapshot"].invoke(args.snapshot_name)
Rake::Task[
"up"].invoke
end

desc
"Vm start"
task :up do
|t|
vbox_command(
"startvm #{test_config.test_vm} --type gui")
puts
'waiting for vm started'
sleep(
5) while not is_vm_started? test_config
puts
"vm #{test_config.test_vm} started"
end

desc
"Vm poweroff "
task :down do
|t|
vbox_command(
"controlvm #{test_config.test_vm} poweroff")
sleep(
5)
end

desc
"Vbox snapshot restore"
task :restore_snapshot,:name do
|t,args|
vbox_command(
"snapshot #{test_config.test_vm} restore \"#{args.name}\"")
end

def vbox_command(vboxCmd,display_result=true)
cmd
="VBoxManage #{vboxCmd}"
puts
"[execute] #{cmd}"
result
=`#{cmd}`
puts result if display_result
result
end

 

触发测试

def windows_test(test_config)
telnet
=os_telnet(test_config)
begin
out
= lambda do |c| print c end
telnet.login(test_config.telnet_user,test_config.telnet_password,
&out)
telnet.cmd(
"tlntadmn config timeoutactive=no",&out)
telnet.cmd(
"net use z: \\\\vboxsvr\\#{test_config.shared_folder_name}", &out)
telnet.cmd(
"set HTTP_PROXY=#{test_config.http_proxy}", &out) if test_config.http_proxy
telnet.cmd(
"set HTTPS_PROXY=#{test_config.https_proxy}", &out) if test_config.https_proxy
telnet.cmd(
"String"=>"cmd.exe /K chef-solo -c z:\\config\\test_solo.rb -j z:\\config\\test_node.json","Timeout"=>false,&out)
telnet.cmd(
"exit",&out)
ensure
telnet.close
end
end

def os_telnet(test_config)
if test_config.windows?
Net::Telnet::new(
"Host"=>"127.0.0.1","Port"=>test_config.telnet_port,"Prompt"=> /.:.*>/)
else
Net::Telnet::new(
"Host"=>"127.0.0.1","Port"=>test_config.telnet_port)
end
end

其他

ruby的Telnet库连接windows有问题,需要打一个猴子补丁。详细见我的帖子:http://ruby-china.org/topics/10774