如何搭建Chef 本地开发环境

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

想达到的效果

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

思路

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

方案

结构图如下:

  1. Test VM需要安装chef-client和Telnet Server.
  2. 开发目录如下
  3. 将当前开发目录设置成VirtualBox的shared folder
  4. Telnet上VM,使用net use(windows)或mount 挂载shared folder
  5. 还是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

 

 

 

posted @ 2013-05-29 18:31  路边飞  阅读(973)  评论(0编辑  收藏  举报