On Sunday, December 9, 2012 at 10:22, Bryan Berry wrote:
I have been struggling lately w/ the problem of how to know whether ornot my servers have been fully provisioned. This is a problem thataffects both cookbook testing and orchestration.I have numerous java applications that have long startup times. Ibelieve Rails 3 apps also have long startup times. For example,elasticsearch takes > 5s to start up fully. However Chef does notnatively have a way to determine when elasticsearch has fully startedup. All Chef can know is the exit code returned by `serviceelasticsearch start` and its various platform equivalents. Why is thisan issue? Well, I don't want to run my minitest-handler integrationtests until elasticsearch is actually functional. Also, if I amtesting a multiple VM setup where another VM depends on elasticsearch,I need to know when elasticsearch has completed startup.Erik Hollensbe is doing some freaking awesome work on workfloworchestration w/ chef-workflow and I think it illustrates the problemhererequire 'chef-workflow/helper'class MyTest < MiniTest::Unit::VagrantTestCasedef before@json_msg = '{ 'id': "dumb message json msg"}'enddef setupprovision('elasticsearch')provision('logstash')wait_for('elasticsearch')wait_for('logstash')inject_logstash_message(@json_msg)enddef test_message_indexed_elasticsearchassert es_has_message?(@json_msg)endendIf I understand Erik's code correctly, the `wait_for('elasticsearch')`only waits for the vagrant provisioner to return. The vagrantprovisioner in turn only waits for `service elasticsearch start` toreturn a non-zero exit-code.We need an optional way to determine whether an server has beencomplete provisioned, or that all the resources have entered a "done"state. The only way I know that elasticsearch has startedsuccessfully is if I see in the log "Elasticsearch has started" w/ atimestamp more recent than when I started the service.Here is my idea, pls tell me if it is crazy.I think that the service resource should have an additional attribute"done" that takes two ruby blocks, named before and after. The firstblock would return a hash with the results of the block.# Warning much of the Ruby code here maybe horribly incorrect.def get_current_offset(file_name){ :offset => ::File.seek(file_name, EOF).get_offset }enddef es_started?(params)!::File.open(params[:log_file], params[:offset],'r').grep(params[:started_text]).empty?endlog_file = '/usr/local/var/log/elasticsearch.log'started_test = "elasticsearch has started successfully"timeout = 60service "elasticsearch" dodone(:before => { get_current_offset(logfile) },:after => { es_started?(:log_file => log_file, :offset=> @before_results[:offset]:timeout => 60)endThe before block would run before the service is actually actioned.Now Chef would need some additional machinery to collect all the done:after blocks and the related @before_results. This could be done bychef_handler but may be better as part of chef itself. Let's call itthe done_handler for now. This done_handler would mark the time beforeit starts handling any done_after blocks, then loop through thecollected done_after blocks for the specified timeout. Once all blocksare complete it would continue onto other handlers, such as theminitest_handler.I think this done_handler could be part of something called "wait_mode"
Archive powered by MHonArc 2.6.16.