<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>chef-server-api/LICENSE</filename>
    </added>
    <added>
      <filename>chef-server-api/README.rdoc</filename>
    </added>
    <added>
      <filename>chef-server-api/Rakefile</filename>
    </added>
    <added>
      <filename>chef-server-api/app/controllers/application.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/controllers/clients.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/controllers/cookbooks.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/controllers/data.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/controllers/data_item.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/controllers/exceptions.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/controllers/main.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/controllers/nodes.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/controllers/roles.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/controllers/search.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/helpers/application_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/helpers/exceptions_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/helpers/global_helpers.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/helpers/nodes_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/helpers/roles_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/views/exceptions/bad_request.json.erb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/views/exceptions/internal_server_error.html.erb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/views/exceptions/not_acceptable.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-api/app/views/exceptions/not_found.html.erb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/views/exceptions/standard_error.html.erb</filename>
    </added>
    <added>
      <filename>chef-server-api/app/views/layout/chef_server_api.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-api/app/views/main/index.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-api/config/init.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/config/router.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/lib/chef-server-api.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/lib/chef-server-api/merbtasks.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/lib/chef-server-api/slicetasks.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/lib/chef-server-api/spectasks.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/public/images/avatar.png</filename>
    </added>
    <added>
      <filename>chef-server-api/public/images/indicator.gif</filename>
    </added>
    <added>
      <filename>chef-server-api/public/images/merb.jpg</filename>
    </added>
    <added>
      <filename>chef-server-api/public/stylesheets/base.css</filename>
    </added>
    <added>
      <filename>chef-server-api/public/stylesheets/chef.css</filename>
    </added>
    <added>
      <filename>chef-server-api/public/stylesheets/themes/bec-green/style.css</filename>
    </added>
    <added>
      <filename>chef-server-api/public/stylesheets/themes/bec/style.css</filename>
    </added>
    <added>
      <filename>chef-server-api/public/stylesheets/themes/blue/style.css</filename>
    </added>
    <added>
      <filename>chef-server-api/public/stylesheets/themes/default/style.css</filename>
    </added>
    <added>
      <filename>chef-server-api/public/stylesheets/themes/djime-cerulean/style.css</filename>
    </added>
    <added>
      <filename>chef-server-api/public/stylesheets/themes/kathleene/style.css</filename>
    </added>
    <added>
      <filename>chef-server-api/public/stylesheets/themes/orange/style.css</filename>
    </added>
    <added>
      <filename>chef-server-api/public/stylesheets/themes/reidb-greenish/style.css</filename>
    </added>
    <added>
      <filename>chef-server-api/stubs/app/controllers/application.rb</filename>
    </added>
    <added>
      <filename>chef-server-api/stubs/app/controllers/main.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/LICENSE</filename>
    </added>
    <added>
      <filename>chef-server-webui/NOTICE</filename>
    </added>
    <added>
      <filename>chef-server-webui/README.rdoc</filename>
    </added>
    <added>
      <filename>chef-server-webui/Rakefile</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/application.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/clients.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/cookbook_attributes.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/cookbook_definitions.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/cookbook_files.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/cookbook_libraries.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/cookbook_recipes.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/cookbook_templates.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/cookbooks.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/databags.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/exceptions.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/main.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/nodes.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/openid_consumer.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/roles.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/search.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/search_entries.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/controllers/status.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/application_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/cookbook_attributes_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/cookbook_definitions_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/cookbook_files_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/cookbook_libraries_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/cookbook_recipes_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/cookbook_templates_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/exceptions_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/global_helpers.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/nodes_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/openid_consumer_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/openid_register_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/openid_server_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/openid_server_helpers.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/roles_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/search_entries_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/search_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/helpers/status_helper.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/clients/_form.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/clients/_navigation.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/clients/edit.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/clients/index.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/clients/new.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/clients/show.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/cookbooks/index.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/cookbooks/show.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/databags/index.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/databags/show.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/exceptions/bad_request.json.erb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/exceptions/internal_server_error.html.erb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/exceptions/not_acceptable.html.erb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/exceptions/not_found.html.erb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/exceptions/standard_error.html.erb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/layout/chef_server_webui.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/layout/login.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/main/index.html.erb</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/nodes/_action.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/nodes/_form.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/nodes/_navigation.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/nodes/_resource.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/nodes/edit.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/nodes/index.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/nodes/new.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/nodes/show.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/openid_consumer/index.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/openid_consumer/start.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/openid_login/index.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/openid_register/index.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/openid_register/show.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/roles/_form.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/roles/_navigation.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/roles/edit.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/roles/index.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/roles/new.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/roles/show.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/search/_search_form.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/search/index.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/search/show.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/search_entries/index.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/search_entries/show.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/app/views/status/index.html.haml</filename>
    </added>
    <added>
      <filename>chef-server-webui/config/init.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/config/router.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/lib/chef-server-webui.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/lib/chef-server-webui/merbtasks.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/lib/chef-server-webui/slicetasks.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/lib/chef-server-webui/spectasks.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/facebox/README.txt</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/facebox/b.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/facebox/bl.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/facebox/br.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/facebox/closelabel.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/facebox/facebox.css</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/facebox/facebox.js</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/facebox/loading.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/facebox/tl.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/facebox/tr.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/avatar.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/black_big.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/indicator.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/merb.jpg</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/toggle-collapse-dark.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/toggle-collapse-light.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/toggle-collapse.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/toggle-expand-dark.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/toggle-expand-light.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/toggle-expand.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/Thumbs.db</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/doc.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/docNode.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/docNodeLast.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/docNodeLastFirst.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/folder.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/folderNode.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/folderNodeFirst.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/folderNodeLast.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/folderNodeLastFirst.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/folderNodeOpen.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/folderNodeOpenFirst.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/folderNodeOpenLast.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/folderNodeOpenLastFirst.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/folderOpen.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/images/treeBuilderImages/vertLine.gif</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/javascripts/JSONeditor.js</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/javascripts/chef.js</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/javascripts/jquery-1.3.2.min.js</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/javascripts/jquery-ui-1.7.1.custom.min.js</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/javascripts/jquery.editinline.js</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/javascripts/jquery.jeditable.mini.js</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/javascripts/jquery.livequery.js</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/javascripts/jquery.localscroll.js</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/javascripts/jquery.scrollTo.js</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/javascripts/jquery.tools.min.js</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/javascripts/jquery.treeTable.min.js</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/base.css</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/chef.css</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-bg_diagonals-small_0_aaaaaa_40x40.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-bg_diagonals-thick_15_444444_40x40.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-bg_glass_100_f0f0f0_1x400.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-bg_glass_50_99c2ff_1x400.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-bg_glass_55_fbf5d0_1x400.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-bg_glass_80_e6e6e6_1x400.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-bg_glass_95_fef1ec_1x400.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-bg_highlight-hard_100_f9f9f9_1x100.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-bg_highlight-soft_100_e7eef3_1x100.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-icons_222222_256x240.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-icons_2694e8_256x240.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-icons_2e83ff_256x240.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-icons_72a7cf_256x240.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-icons_888888_256x240.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-icons_cd0a0a_256x240.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/images/ui-icons_ffffff_256x240.png</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/jquery-ui-1.7.1.custom.css</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/jquery.treeTable.css</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/themes/bec-green/style.css</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/themes/bec/style.css</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/themes/blue/style.css</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/themes/default/style.css</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/themes/djime-cerulean/style.css</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/themes/kathleene/style.css</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/themes/orange/style.css</filename>
    </added>
    <added>
      <filename>chef-server-webui/public/stylesheets/themes/reidb-greenish/style.css</filename>
    </added>
    <added>
      <filename>chef-server-webui/stubs/app/controllers/application.rb</filename>
    </added>
    <added>
      <filename>chef-server-webui/stubs/app/controllers/main.rb</filename>
    </added>
    <added>
      <filename>chef-solr/.document</filename>
    </added>
    <added>
      <filename>chef-solr/.gitignore</filename>
    </added>
    <added>
      <filename>chef-solr/README.rdoc</filename>
    </added>
    <added>
      <filename>chef-solr/Rakefile</filename>
    </added>
    <added>
      <filename>chef-solr/VERSION</filename>
    </added>
    <added>
      <filename>chef-solr/bin/chef-solr</filename>
    </added>
    <added>
      <filename>chef-solr/bin/chef-solr-indexer</filename>
    </added>
    <added>
      <filename>chef-solr/bin/chef-solr-rebuild</filename>
    </added>
    <added>
      <filename>chef-solr/chef-solr.gemspec</filename>
    </added>
    <added>
      <filename>chef-solr/lib/chef/solr.rb</filename>
    </added>
    <added>
      <filename>chef-solr/lib/chef/solr/application/indexer.rb</filename>
    </added>
    <added>
      <filename>chef-solr/lib/chef/solr/application/rebuild.rb</filename>
    </added>
    <added>
      <filename>chef-solr/lib/chef/solr/application/solr.rb</filename>
    </added>
    <added>
      <filename>chef-solr/lib/chef/solr/index.rb</filename>
    </added>
    <added>
      <filename>chef-solr/lib/chef/solr/index_actor.rb</filename>
    </added>
    <added>
      <filename>chef-solr/lib/chef/solr/query.rb</filename>
    </added>
    <added>
      <filename>chef-solr/solr/solr-home.tar.gz</filename>
    </added>
    <added>
      <filename>chef-solr/solr/solr-jetty.tar.gz</filename>
    </added>
    <added>
      <filename>chef-solr/spec/chef/solr/index_spec.rb</filename>
    </added>
    <added>
      <filename>chef-solr/spec/chef/solr/query_spec.rb</filename>
    </added>
    <added>
      <filename>chef-solr/spec/chef/solr_spec.rb</filename>
    </added>
    <added>
      <filename>chef-solr/spec/spec_helper.rb</filename>
    </added>
    <added>
      <filename>chef/bin/knife</filename>
    </added>
    <added>
      <filename>chef/lib/chef/api_client.rb</filename>
    </added>
    <added>
      <filename>chef/lib/chef/certificate.rb</filename>
    </added>
    <added>
      <filename>chef/lib/chef/data_bag.rb</filename>
    </added>
    <added>
      <filename>chef/lib/chef/data_bag_item.rb</filename>
    </added>
    <added>
      <filename>chef/lib/chef/nanite.rb</filename>
    </added>
    <added>
      <filename>chef/lib/chef/search/query.rb</filename>
    </added>
    <added>
      <filename>chef/lib/chef/streaming_cookbook_uploader.rb</filename>
    </added>
    <added>
      <filename>chef/spec/unit/api_client_spec.rb</filename>
    </added>
    <added>
      <filename>chef/spec/unit/certificate_spec.rb</filename>
    </added>
    <added>
      <filename>chef/spec/unit/data_bag_item_spec.rb</filename>
    </added>
    <added>
      <filename>chef/spec/unit/data_bag_spec.rb</filename>
    </added>
    <added>
      <filename>chef/spec/unit/search/query_spec.rb</filename>
    </added>
    <added>
      <filename>features/api/clients/create_client_api.feature</filename>
    </added>
    <added>
      <filename>features/api/clients/delete_client_api.feature</filename>
    </added>
    <added>
      <filename>features/api/clients/list_clients_api.feature</filename>
    </added>
    <added>
      <filename>features/api/clients/show_client_api.feature</filename>
    </added>
    <added>
      <filename>features/api/clients/update_client_api.feature</filename>
    </added>
    <added>
      <filename>features/api/cookbooks/list_cookbooks_api.feature</filename>
    </added>
    <added>
      <filename>features/api/cookbooks/show_cookbook_api.feature</filename>
    </added>
    <added>
      <filename>features/api/cookbooks/show_cookbook_attributes_api.feature</filename>
    </added>
    <added>
      <filename>features/api/data/create_data_bag_api.feature</filename>
    </added>
    <added>
      <filename>features/api/data/create_data_bag_item_api.feature</filename>
    </added>
    <added>
      <filename>features/api/data/delete_data_bag_api.feature</filename>
    </added>
    <added>
      <filename>features/api/data/delete_data_bag_item.feature</filename>
    </added>
    <added>
      <filename>features/api/data/list_data_bags.feature</filename>
    </added>
    <added>
      <filename>features/api/data/show_data_bag_api.feature</filename>
    </added>
    <added>
      <filename>features/api/data/show_data_bag_item_api.feature</filename>
    </added>
    <added>
      <filename>features/api/nodes/cookbook_sync_api.feature</filename>
    </added>
    <added>
      <filename>features/api/search/list_search.feature</filename>
    </added>
    <added>
      <filename>features/api/search/show_search.feature</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/node_cookbook_sync/README.rdoc</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/node_cookbook_sync/attributes/attr_file.rb</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/node_cookbook_sync/definitions/def_file.rb</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/node_cookbook_sync/libraries/lib_file.rb</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/node_cookbook_sync/metadata.rb</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/node_cookbook_sync/recipes/default.rb</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/search/recipes/search_data_noblock.rb</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/show_cookbook/README.rdoc</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/show_cookbook/attributes/attr_file.rb</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/show_cookbook/definitions/def_file.rb</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/show_cookbook/files/default/prime_time.txt</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/show_cookbook/files/host-latte/prime_time.txt</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/show_cookbook/files/mac_os_x-10.5/prime_time.txt</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/show_cookbook/files/mac_os_x/prime_time.txt</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/show_cookbook/libraries/lib_file.rb</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/show_cookbook/metadata.rb</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/show_cookbook/recipes/default.rb</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/show_cookbook/templates/default/prime_time.txt.erb</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/show_cookbook/templates/host-latte/prime_time.txt.erb</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/show_cookbook/templates/mac_os_x-10.5/prime_time.txt.erb</filename>
    </added>
    <added>
      <filename>features/data/cookbooks/show_cookbook/templates/mac_os_x/prime_time.txt.erb</filename>
    </added>
    <added>
      <filename>features/data/node-load-test.rb</filename>
    </added>
    <added>
      <filename>scripts/mac-dev-start</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,3 +1,29 @@
+Mon Sep 27 6:22:00 NZST 2009
+
+Release Notes - Chef - Version 0.7.14
+
+** Bug
+    * [CHEF-454] - Centos4 yum provider failure
+    * [CHEF-565] - dpkg provider fails at packages with a dash in it, causing packages to be re-installed on every chef run
+    * [CHEF-570] - Portage package provider uses wrong regexp in load_current_resource
+    * [CHEF-577] - provider.rb doesn't give @definitions a default value of Hash.new, causing epic fail in resource DSL 
+    * [CHEF-588] - RC is missing debugging info in find_preferred_file
+    * [CHEF-591] - if service doesn't have a status command, process table inspection fails in simple service provider
+    * [CHEF-593] - deploy resource is not idempotent
+    * [CHEF-602] - in deploy provider, callback-defined resources are executed in all subsequent callbacks
+    * [CHEF-603] - deploy: gems.yml support
+    * [CHEF-604] - deploy: sudo / run command handler support
+    * [CHEF-614] - LWRP  undefined local variable or method `new_resource'
+    * [CHEF-619] - Mixlib-* gems installed from gemcutter.org have too restrictive permissions
+    * [CHEF-621] - LWRP dynamic attribute methods are Ruby 1.9 incompatible and cause warnings in 1.8
+    * [CHEF-628] - Deploy resource removes newest release instead of oldest
+
+** Improvement
+    * [CHEF-620] - LWRP components should be shown in Web UI
+    * [CHEF-622] - Gem Package resource/provider shouldn't silently ignore the options attribute
+    * [CHEF-631] - Should create LWRP resources/providers for new_cookbook
+
+
 Fri Sep 4 7:25:00 NZST 2009
 
 Release Notes - Chef - Version 0.7.12</diff>
      <filename>CHANGELOG</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-gems = %w[chef chef-server-slice chef-server]
+gems = %w[chef chef-server-api chef-server-webui chef-server chef-solr]
 require 'rubygems'
 require 'cucumber/rake/task'
 
@@ -26,71 +26,136 @@ end
 desc &quot;Run the rspec tests&quot;
 task :spec do
   Dir.chdir(&quot;chef&quot;) { sh &quot;rake spec&quot; }
+  Dir.chdir(&quot;chef-solr&quot;) { sh &quot;rake spec&quot; }
 end
 
 task :default =&gt; :spec
 
-def start_dev_environment(type=&quot;normal&quot;)
-  @couchdb_server_pid = nil
-  @chef_server_pid    = nil
-  @chef_indexer_pid   = nil
-  @stompserver_pid    = nil
-  
-  ccid = fork
-  if ccid
-    @couchdb_server_pid = ccid
+def start_couchdb(type=&quot;normal&quot;)
+  @couchdb_server_pid  = nil
+  cid = fork
+  if cid
+    @couchdb_server_pid = cid
   else
     exec(&quot;couchdb&quot;)
   end
+end
 
-  scid = fork
-  if scid
-    @stompserver_pid = scid
+def start_rabbitmq(type=&quot;normal&quot;)
+  @rabbitmq_server_pid = nil
+  cid = fork
+  if cid
+    @rabbitmq_server_pid = cid
   else
-    exec(&quot;stompserver&quot;)
+    exec(&quot;rabbitmq-server&quot;)
   end
+end
 
-  mcid = fork
-  if mcid # parent
-    @chef_indexer_pid = mcid
-  else # child
+def configure_rabbitmq(type=&quot;normal&quot;)
+  # hack. wait for rabbit to come up.
+  sleep 2
+  
+  puts `rabbitmqctl add_vhost /nanite`
+
+  # create 'mapper' and 'nanite' users, give them each the password 'testing'
+  %w[mapper nanite].each do |agent|
+    puts `rabbitmqctl add_user #{agent} testing`
+  end
+
+  # grant the mapper user the ability to do anything with the /nanite vhost
+  # the three regex's map to config, write, read permissions respectively
+  puts `rabbitmqctl set_permissions -p /nanite mapper &quot;.*&quot; &quot;.*&quot; &quot;.*&quot;`
+
+  # grant the nanite user more limited permissions on the /nanite vhost
+  puts `rabbitmqctl set_permissions -p /nanite nanite &quot;.*&quot; &quot;.*&quot; &quot;.*&quot;`
+
+  puts `rabbitmqctl list_users`
+  puts `rabbitmqctl list_vhosts`
+  puts `rabbitmqctl list_permissions -p /nanite`
+  
+end
+
+def start_chef_solr(type=&quot;normal&quot;)
+  @chef_solr_pid = nil
+  cid = fork
+  if cid
+    @chef_solr_pid = cid
+  else
     case type
     when &quot;normal&quot;
-      exec(&quot;chef-indexer -l debug&quot;)
+      exec(&quot;./chef-solr/bin/chef-solr -l debug&quot;)
     when &quot;features&quot;
-      exec(&quot;chef-indexer -c #{File.join(File.dirname(__FILE__), &quot;features&quot;, &quot;data&quot;, &quot;config&quot;, &quot;server.rb&quot;)} -l debug&quot;)
+      exec(&quot;./chef-solr/bin/chef-solr -c #{File.join(File.dirname(__FILE__), &quot;features&quot;, &quot;data&quot;, &quot;config&quot;, &quot;server.rb&quot;)} -l debug&quot;)
     end
   end
+end
+
+def start_chef_solr_indexer(type=&quot;normal&quot;)
+  @chef_solr_indexer   = nil
+  cid = fork
+  if cid
+    @chef_solr_indexer_pid = cid
+  else
+    case type
+    when &quot;normal&quot;
+      exec(&quot;./chef-solr/bin/chef-solr-indexer -l debug&quot;)
+    when &quot;features&quot;
+      exec(&quot;./chef-solr/bin/chef-solr-indexer -c #{File.join(File.dirname(__FILE__), &quot;features&quot;, &quot;data&quot;, &quot;config&quot;, &quot;server.rb&quot;)} -l debug&quot;)
+    end
+  end
+end
 
+def start_chef_server(type=&quot;normal&quot;)
+  @chef_server_pid     = nil
   mcid = fork
   if mcid # parent
     @chef_server_pid = mcid
   else # child
     case type
     when &quot;normal&quot;
-      exec(&quot;chef-server -l debug -N -c 2&quot;)
+      exec(&quot;./chef-server/bin/chef-server -a thin -l debug -N&quot;)
     when &quot;features&quot;
-      exec(&quot;chef-server -C #{File.join(File.dirname(__FILE__), &quot;features&quot;, &quot;data&quot;, &quot;config&quot;, &quot;server.rb&quot;)} -l debug -N -c 2&quot;)
-      
+      exec(&quot;./chef-server/bin/chef-server -a thin -C #{File.join(File.dirname(__FILE__), &quot;features&quot;, &quot;data&quot;, &quot;config&quot;, &quot;server.rb&quot;)} -l debug -N&quot;)
     end
   end
+end
 
-  puts &quot;Running Chef at #{@chef_server_pid}&quot;
-  puts &quot;Running Chef Indexer at #{@chef_indexer_pid}&quot;
+def start_dev_environment(type=&quot;normal&quot;)
+  start_couchdb(type)
+  start_rabbitmq(type)
+  configure_rabbitmq(type)
+  start_chef_solr(type)
+  start_chef_solr_indexer(type)
+  start_chef_server(type)
   puts &quot;Running CouchDB at #{@couchdb_server_pid}&quot;
-  puts &quot;Running Stompserver at #{@stompserver_pid}&quot;
+  puts &quot;Running RabbitMQ at #{@rabbitmq_server_pid}&quot;
+  puts &quot;Running Chef Solr at #{@chef_solr_pid}&quot;
+  puts &quot;Running Chef Solr Indexer at #{@chef_solr_indexer_pid}&quot;
+  puts &quot;Running Chef at #{@chef_server_pid}&quot;
 end
 
 def stop_dev_environment
-  puts &quot;Stopping CouchDB&quot;
-  Process.kill(&quot;KILL&quot;, @couchdb_server_pid) 
-  puts &quot;Stopping Stomp server&quot;
-  Process.kill(&quot;KILL&quot;, @stompserver_pid) 
-  puts &quot;Stopping Chef Server&quot;
-  Process.kill(&quot;INT&quot;, @chef_server_pid)
-  puts &quot;Stopping Chef Indexer&quot;
-  Process.kill(&quot;INT&quot;, @chef_indexer_pid)
-  puts &quot;\nCouchDB, Stomp, Chef Server and Chef Indexer killed - have a nice day!&quot;
+  if @chef_server_pid
+    puts &quot;Stopping Chef&quot;
+    Process.kill(&quot;KILL&quot;, @chef_server_pid)
+  end
+  if @chef_solr_pid
+    puts &quot;Stopping Chef Solr&quot;
+    Process.kill(&quot;INT&quot;, @chef_solr_pid)
+  end
+  if @chef_solr_indexer_pid
+    puts &quot;Stopping Chef Solr Indexer&quot;
+    Process.kill(&quot;INT&quot;, @chef_solr_indexer_pid)
+  end
+  if @couchdb_server_pid
+    puts &quot;Stopping CouchDB&quot;
+    Process.kill(&quot;KILL&quot;, @couchdb_server_pid) 
+  end
+  if @rabbitmq_server_pid
+    puts &quot;Stopping RabbitMQ&quot;
+    Process.kill(&quot;KILL&quot;, @rabbitmq_server_pid) 
+  end
+  puts &quot;Have a nice day!&quot;
 end
 
 def wait_for_ctrlc
@@ -106,7 +171,7 @@ def wait_for_ctrlc
 end
 
 desc &quot;Run a Devel instance of Chef&quot;
-task :dev =&gt; &quot;dev:install&quot; do
+task :dev do
   start_dev_environment
   wait_for_ctrlc
 end
@@ -114,12 +179,78 @@ end
 namespace :dev do  
   desc &quot;Install a test instance of Chef for doing features against&quot;
   task :features do
-    gems.each do |dir|
-      Dir.chdir(dir) { sh &quot;rake install&quot; }
-    end
     start_dev_environment(&quot;features&quot;)
     wait_for_ctrlc
   end
+
+  namespace :features do
+    
+    namespace :start do
+      desc &quot;Start CouchDB for testing&quot;
+      task :couchdb do
+        start_couchdb(&quot;features&quot;)
+        wait_for_ctrlc
+      end
+
+      desc &quot;Start RabbitMQ for testing&quot;
+      task :rabbitmq do
+        start_rabbitmq(&quot;features&quot;)
+        configure_rabbitmq(&quot;features&quot;)
+        wait_for_ctrlc
+      end
+      
+      desc &quot;Start Chef Solr for testing&quot;
+      task :chef_solr do
+        start_chef_solr(&quot;features&quot;)
+        wait_for_ctrlc
+      end
+
+      desc &quot;Start Chef Solr Indexer for testing&quot;
+      task :chef_solr_indexer do
+        start_chef_solr_indexer(&quot;features&quot;)
+        wait_for_ctrlc
+      end
+
+      desc &quot;Start Chef Server for testing&quot;
+      task :chef_server do
+        start_chef_server(&quot;features&quot;)
+        wait_for_ctrlc
+      end
+
+    end
+  end
+
+  namespace :start do
+    desc &quot;Start CouchDB&quot;
+    task :couchdb do
+      start_couchdb
+      wait_for_ctrlc
+    end
+
+    desc &quot;Start RabbitMQ&quot;
+    task :rabbitmq do
+      start_rabbitmq
+      wait_for_ctrlc
+    end
+
+    desc &quot;Start Chef Solr&quot;
+    task :chef_solr do
+      start_chef_solr
+      wait_for_ctrlc
+    end
+
+    desc &quot;Start Chef Solr Indexer&quot;
+    task :chef_solr_indexer do
+      start_chef_solr_indexer
+      wait_for_ctrlc
+    end
+
+    desc &quot;Start Chef Server&quot;
+    task :chef_server do
+      start_chef_server
+      wait_for_ctrlc
+    end
+  end
 end
 
 Cucumber::Rake::Task.new(:features) do |t|
@@ -127,12 +258,13 @@ Cucumber::Rake::Task.new(:features) do |t|
 end
 
 namespace :features do
+  desc &quot;Run cucumber tests for the REST API&quot;
   Cucumber::Rake::Task.new(:api) do |t|
     t.profile = &quot;api&quot;
   end
 
   namespace :api do
-    [ :nodes, :roles].each do |api|
+    [ :nodes, :roles, :clients ].each do |api|
         Cucumber::Rake::Task.new(api) do |apitask|
           apitask.profile = &quot;api_#{api.to_s}&quot;
         end
@@ -144,8 +276,54 @@ namespace :features do
         end
       end
     end
+
+    namespace :nodes do
+      Cucumber::Rake::Task.new(&quot;sync&quot;) do |t|
+        t.profile = &quot;api_nodes_sync&quot;
+      end
+    end
+
+    namespace :cookbooks do    
+      desc &quot;Run cucumber tests for the cookbooks portion of the REST API&quot;
+      Cucumber::Rake::Task.new(:cookbooks) do |t|
+        t.profile = &quot;api_cookbooks&quot;
+      end
+    end
+    
+    namespace :data do    
+      desc &quot;Run cucumber tests for the data portion of the REST API&quot;
+      Cucumber::Rake::Task.new(:data) do |t|
+        t.profile = &quot;api_data&quot;
+      end
+      
+      desc &quot;Run cucumber tests for deleting data via the REST API&quot;
+      Cucumber::Rake::Task.new(:delete) do |t|
+        t.profile = &quot;api_data_delete&quot;
+      end
+      desc &quot;Run cucumber tests for adding items via the REST API&quot;
+      Cucumber::Rake::Task.new(:item) do |t|
+        t.profile = &quot;api_data_item&quot;
+      end
+    end
+    
+    namespace :search do
+      desc &quot;Run cucumber tests for searching via the REST API&quot;
+      Cucumber::Rake::Task.new(:search) do |t|
+        t.profile = &quot;api_search&quot;
+      end
+      
+      desc &quot;Run cucumber tests for listing search endpoints via the REST API&quot;
+      Cucumber::Rake::Task.new(:list) do |t|
+        t.profile = &quot;api_search_list&quot;
+      end
+      desc &quot;Run cucumber tests for searching via the REST API&quot;
+      Cucumber::Rake::Task.new(:show) do |t|
+        t.profile = &quot;api_search_show&quot;
+      end
+    end
   end
 
+  desc &quot;Run cucumber tests for the chef client&quot;
   Cucumber::Rake::Task.new(:client) do |t|
     t.profile = &quot;client&quot;
   end
@@ -154,8 +332,23 @@ namespace :features do
     Cucumber::Rake::Task.new(:roles) do |t|
       t.profile = &quot;client_roles&quot;
     end
+
+    Cucumber::Rake::Task.new(:run_interval) do |t|
+      t.profile = &quot;client_run_interval&quot;
+    end
   end
 
+  desc &quot;Run cucumber tests for the cookbooks&quot;
+  Cucumber::Rake::Task.new(:cookbooks) do |t|
+    t.profile = &quot;cookbooks&quot;
+  end
+
+  desc &quot;Run cucumber tests for the recipe language&quot;
+  Cucumber::Rake::Task.new(:language) do |t|
+    t.profile = &quot;language&quot;
+  end
+
+  desc &quot;Run cucumber tests for searching in recipes&quot;
   Cucumber::Rake::Task.new(:search) do |t|
     t.profile = &quot;search&quot;
   end
@@ -173,21 +366,50 @@ namespace :features do
   Cucumber::Rake::Task.new(:lwrp) do |t|
     t.profile = &quot;lwrp&quot;
   end
+
+  desc &quot;Run cucumber tests for providers&quot; 
+  Cucumber::Rake::Task.new(:provider) do |t|
+    t.profile = &quot;provider&quot;
+  end
+
   
   namespace :provider do
-    Cucumber::Rake::Task.new(:template) do |t|
-      t.profile = &quot;provider_template&quot;
+    desc &quot;Run cucumber tests for deploy resources&quot;
+    Cucumber::Rake::Task.new(:deploy) do |t|
+      t.profile = &quot;provider_deploy&quot;
+    end
+
+    desc &quot;Run cucumber tests for directory resources&quot;
+    Cucumber::Rake::Task.new(:directory) do |t|
+      t.profile = &quot;provider_directory&quot;
+    end
+
+    desc &quot;Run cucumber tests for execute resources&quot;
+    Cucumber::Rake::Task.new(:execute) do |t|
+      t.profile = &quot;provider_execute&quot;
     end
 
+    desc &quot;Run cucumber tests for file resources&quot;
+    Cucumber::Rake::Task.new(:file) do |t|
+      t.profile = &quot;provider_file&quot;
+    end
+
+    desc &quot;Run cucumber tests for remote_file resources&quot;
     Cucumber::Rake::Task.new(:remote_file) do |t|
       t.profile = &quot;provider_remote_file&quot;
     end
+
+    desc &quot;Run cucumber tests for template resources&quot;
+    Cucumber::Rake::Task.new(:template) do |t|
+      t.profile = &quot;provider_template&quot;
+    end
     
     Cucumber::Rake::Task.new(:git) do |t|
       t.profile = &quot;provider_git&quot;
     end
     
     namespace :package do
+      desc &quot;Run cucumber tests for macports packages&quot;
       Cucumber::Rake::Task.new(:macports) do |t|
         t.profile = &quot;provider_package_macports&quot;
       end</diff>
      <filename>Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -18,7 +18,7 @@ require 'chef' unless defined?(Chef)
 include FileUtils
 
 GEM = &quot;chef-server&quot;
-CHEF_SERVER_VERSION = &quot;0.7.12&quot;
+CHEF_SERVER_VERSION = &quot;0.8.0&quot;
 AUTHOR = &quot;Opscode&quot;
 EMAIL = &quot;chef@opscode.com&quot;
 HOMEPAGE = &quot;http://wiki.opscode.com/display/chef&quot;</diff>
      <filename>chef-server/Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -26,7 +26,8 @@
 require &quot;rubygems&quot;
 require &quot;merb-core&quot;
 
-[ 'chef', 'chef-server-slice' ].each do |lib|
+[ 'chef', 'chef-server-api' ].each do |lib|
+  $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;..&quot;, &quot;lib&quot;)))
   library = File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;..&quot;, lib, &quot;lib&quot;, &quot;#{lib}.rb&quot;)
   require library if File.exists?(library)
 end
@@ -50,7 +51,7 @@ if ARGV[0] &amp;&amp; ARGV[0] =~ /^[^-]/
   ARGV.push &quot;-H&quot;
 end 
 unless %w[-a --adapter -i --irb-console -r --script-runner].any? { |o| ARGV.index(o) }
-  ARGV.push *%w[-a mongrel]
+  ARGV.push *%w[-a thin]
 end
 ARGV.push *[ &quot;-I&quot;, File.join(__DIR__, &quot;config&quot;, &quot;init.rb&quot;) ]
 ARGV.push *[ &quot;-m&quot;, __DIR__]</diff>
      <filename>chef-server/bin/chef-server</filename>
    </modified>
    <modified>
      <diff>@@ -4,8 +4,10 @@ require 'chef'
 
 Chef::Config.from_file(File.join(&quot;/etc&quot;, &quot;chef&quot;, &quot;server.rb&quot;))
 
-Merb::Config.setup(:merb_root   =&gt; File.expand_path(File.dirname(__FILE__)),
-                   :environment =&gt; ENV['RACK_ENV'], :init_file =&gt; File.dirname(__FILE__) / &quot;config/init.rb&quot;)
+Merb::Config.setup(:merb_root   =&gt; File.expand_path(File.dirname(__FILE__)), 
+                   :environment =&gt; ENV['RACK_ENV'], 
+                   :fork_for_class_load =&gt; false,
+                   :init_file =&gt; File.dirname(__FILE__) / &quot;config/init.rb&quot;)
 Merb.environment = Merb::Config[:environment]
 Merb.root = Merb::Config[:merb_root]
 Merb::BootLoader.run</diff>
      <filename>chef-server/config.ru</filename>
    </modified>
    <modified>
      <diff>@@ -1,13 +1,24 @@
 # dependencies are generated using a strict version, don't forget to edit the dependency versions when upgrading.
 merb_gems_version = &quot;&gt; 1.0&quot;
 
+%w{chef chef-server-api chef-solr}.each do |dep|
+  $:.unshift(File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;..&quot;, dep, &quot;lib&quot;))
+end
+
+begin
+  require 'chef'
+  require 'chef-server-api'
+rescue
+end
+  
 # For more information about each component, please read http://wiki.merbivore.com/faqs/merb_components
 dependency &quot;merb-core&quot;, merb_gems_version 
 dependency &quot;merb-assets&quot;, merb_gems_version  
 dependency &quot;merb-helpers&quot;, merb_gems_version 
 dependency &quot;merb-slices&quot;, merb_gems_version  
 if defined?(CHEF_SERVER_VERSION)
-  dependency &quot;chef-server-slice&quot;, CHEF_SERVER_VERSION unless defined?(ChefServerSlice)
+  dependency &quot;chef-server-api&quot;, CHEF_SERVER_VERSION unless defined?(ChefServerApi)
 else
-  dependency &quot;chef-server-slice&quot; unless defined?(ChefServerSlice)
+  dependency &quot;chef-server-api&quot; unless defined?(ChefServerApi)
 end
+</diff>
      <filename>chef-server/config/dependencies.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,6 @@ Merb::Config.use { |c|
   c[:reload_templates] = true
   c[:reload_classes] = true
   c[:reload_time] = 0.5
-  c[:ignore_tampered_cookies] = true
   c[:log_auto_flush ] = true
   c[:log_level] = :debug
   c[:log_stream] = Chef::Config[:log_location]</diff>
      <filename>chef-server/config/environments/development.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,7 @@ Merb.logger.info(&quot;Loaded PRODUCTION Environment...&quot;)
 Merb::Config.use { |c|
   c[:exception_details] = false
   c[:reload_classes] = false
+  c[:log_auto_flush] = true
   c[:log_level] = Chef::Config[:log_level]
   c[:log_stream] = Chef::Config[:log_location]
   # or redirect logger using IO handle</diff>
      <filename>chef-server/config/environments/production.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,5 @@
 # Go to http://wiki.merbivore.com/pages/init-rb
- 
+
 require 'config/dependencies.rb'
 unless defined?(Chef)
   gem &quot;chef&quot;, &quot;=&quot; + CHEF_SERVER_VERSION if CHEF_SERVER_VERSION
@@ -11,13 +11,10 @@ use_template_engine :haml
 
 Merb::Config.use do |c|
   c[:use_mutex] = false
-  c[:session_id_key] = '_chef_server_session_id'
-  c[:session_secret_key]  = Chef::Config.manage_secret_key
-  c[:session_store] = 'cookie'
-  c[:exception_details] = true
-  c[:reload_classes] = false
   c[:log_level] = Chef::Config[:log_level]
-  c[:log_stream] = Chef::Config[:log_location]
+  if Chef::Config[:log_location].kind_of?(String)
+    c[:log_file] = Chef::Config[:log_location]
+  end
 end
  
 Merb::BootLoader.before_app_loads do
@@ -25,6 +22,6 @@ Merb::BootLoader.before_app_loads do
 end
  
 Merb::BootLoader.after_app_loads do
-  # This will get executed after your app's classes have been loaded.
-  OpenID::Util.logger = Merb.logger
+  # This will get executed after your app's classes have been loaded.  OpenID::Util.logger = Merb.logger
 end
+</diff>
      <filename>chef-server/config/init.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,5 @@
+$: &lt;&lt; File.join(File.dirname(__FILE__))
+
 # use PathPrefix Middleware if :path_prefix is set in Merb::Config
 if prefix = ::Merb::Config[:path_prefix]
   use Merb::Rack::PathPrefix, prefix</diff>
      <filename>chef-server/config/rack.rb</filename>
    </modified>
    <modified>
      <diff>@@ -29,16 +29,11 @@ Merb.logger.info(&quot;Compiling routes...&quot;)
 Merb::Router.prepare do
   # RESTful routes
   # resources :posts
-  
+ 
   # Adds the required routes for merb-auth using the password slice
   # slice(:merb_auth_slice_password, :name_prefix =&gt; nil, :path_prefix =&gt; &quot;&quot;)
-  slice(:chef_server_slice)
-  # This is the default route for /:controller/:action/:id
-  # This is fine for most cases.  If you're heavily using resource-based
-  # routes, you may want to comment/remove this line to prevent
-  # clients from calling your create or destroy actions with a GET
-  default_routes
-  
-  # Change this for your home page to be available at /
-  # match('/').to(:controller =&gt; 'whatever', :action =&gt;'index')
+
+  slice(:chef_server_api)
+  # slice(:chef_server_webui, :path_prefix =&gt; &quot;html&quot;)
+
 end</diff>
      <filename>chef-server/config/router.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@ require 'rake/rdoctask'
 require './tasks/rspec.rb'
 
 GEM = &quot;chef&quot;
-CHEF_VERSION = &quot;0.7.12&quot;
+CHEF_VERSION = &quot;0.8.0&quot;
 AUTHOR = &quot;Adam Jacob&quot;
 EMAIL = &quot;adam@opscode.com&quot;
 HOMEPAGE = &quot;http://wiki.opscode.com/display/chef&quot;
@@ -23,13 +23,11 @@ spec = Gem::Specification.new do |s|
   s.homepage = HOMEPAGE
   
   s.add_dependency &quot;mixlib-config&quot;, &quot;&gt;= 1.0.12&quot;
-  s.add_dependency &quot;ohai&quot;, &quot;&gt;= 0.3.4&quot;
-  %w{mixlib-cli mixlib-log ruby-openid
-    json erubis extlib
-    stomp}.each { |gem| s.add_dependency gem }
+  s.add_dependency &quot;ohai&quot;, &quot;&gt;= 0.3.6&quot;
+  %w{mixlib-cli mixlib-log mixlib-authentication json erubis extlib amqp thor ruby-hmac}.each { |gem| s.add_dependency gem }
   
   s.bindir       = &quot;bin&quot;
-  s.executables  = %w( chef-client chef-solo )
+  s.executables  = %w( chef-client chef-solo knife )
   s.require_path = 'lib'
   s.files = %w(LICENSE README.rdoc) + Dir.glob(&quot;{distro,lib}/**/*&quot;)
 end</diff>
      <filename>chef/Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -18,9 +18,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-$: &lt;&lt; File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;lib&quot;)
+$:.unshift(File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;lib&quot;))
 
 require 'rubygems'
 require 'chef/application/client'
 
-Chef::Application::Client.new.run
\ No newline at end of file
+Chef::Application::Client.new.run</diff>
      <filename>chef/bin/chef-client</filename>
    </modified>
    <modified>
      <diff>@@ -18,7 +18,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-$: &lt;&lt; File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;lib&quot;)
+$:.unshift(File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;lib&quot;))
 
 require 'rubygems'
 require 'chef/application/solo'</diff>
      <filename>chef/bin/chef-solo</filename>
    </modified>
    <modified>
      <diff>@@ -27,7 +27,7 @@ require 'chef/config'
 Dir[File.join(File.dirname(__FILE__), 'chef/mixin/**/*.rb')].sort.each { |lib| require lib }
 
 class Chef
-  VERSION = '0.7.12'
+  VERSION = '0.8.0'
 end
 
 # Adds a Dir.glob to Ruby 1.8.5, for compat</diff>
      <filename>chef/lib/chef.rb</filename>
    </modified>
    <modified>
      <diff>@@ -153,6 +153,11 @@ class Chef::Application::Client &lt; Chef::Application
       end
     end
   end
+
+  def configure_logging
+    super
+    Mixlib::Authentication::Log.logger = Chef::Log.logger
+  end
   
   # Setup an instance of the chef client
   # Why is this so ugly? surely the client should just read out of chef::config instead of needing the values to be assigned like this..</diff>
      <filename>chef/lib/chef/application/client.rb</filename>
    </modified>
    <modified>
      <diff>@@ -15,4 +15,5 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-require 'chef/application'
\ No newline at end of file
+require 'chef/application'
+</diff>
      <filename>chef/lib/chef/application/server.rb</filename>
    </modified>
    <modified>
      <diff>@@ -47,9 +47,14 @@ class Chef
       @json_attribs = nil
       @node_name = nil
       @node_exists = true 
-      Ohai::Log.logger = Chef::Log.logger
+      Mixlib::Authentication::Log.logger = Ohai::Log.logger = Chef::Log.logger
       @ohai = Ohai::System.new
-      @rest = Chef::REST.new(Chef::Config[:registration_url])
+      @ohai_has_run = false
+      if File.exists?(Chef::Config[:client_key])
+        @rest = Chef::REST.new(Chef::Config[:chef_server_url])
+      else
+        @rest = Chef::REST.new(Chef::Config[:chef_server_url], nil, nil)
+      end
     end
     
     # Do a full run for this Chef::Client.  Calls:
@@ -76,15 +81,9 @@ class Chef
       
       determine_node_name
       register
-      authenticate
       build_node(@node_name)
       save_node
-      sync_library_files
-      sync_provider_files
-      sync_resource_files
-      sync_attribute_files
-      sync_definitions
-      sync_recipes
+      sync_cookbooks
       save_node
       converge
       save_node
@@ -123,9 +122,14 @@ class Chef
     end
 
     def determine_node_name
-      run_ohai
+      run_ohai      
       unless safe_name &amp;&amp; node_name
-        @node_name ||= @ohai[:fqdn] ? @ohai[:fqdn] : @ohai[:hostname]
+        if Chef::Config[:node_name]
+          @node_name = Chef::Config[:node_name]
+        else
+          @node_name ||= @ohai[:fqdn] ? @ohai[:fqdn] : @ohai[:hostname]
+          Chef::Config[:node_name] = @node_name
+        end
         @safe_name = @node_name.gsub(/\./, '_')
       end
       @node_name
@@ -184,68 +188,22 @@ class Chef
       @node[:tags] = Array.new unless @node.attribute?(:tags)
       @node
     end
-    
-    # If this node has been registered before, this method will fetch the current registration
-    # data.
-    #
-    # If it has not, we register it by calling create_registration.
-    #
+   
+    # 
     # === Returns
     # true:: Always returns true
     def register
-      determine_node_name unless @node_name
-      Chef::Log.debug(&quot;Registering #{@safe_name} for an openid&quot;) 
-      
-      begin
-        if @rest.get_rest(&quot;registrations/#{@safe_name}&quot;)
-          @secret = Chef::FileCache.load(File.join(&quot;registration&quot;, @safe_name))
-        end
-      rescue Net::HTTPServerException =&gt; e
-        case e.message
-        when /^404/
-          create_registration
-        else
-          raise
-        end
-      rescue Chef::Exceptions::FileNotFound
-        Chef::Application.fatal! &quot;A remote registration already exists for #{@safe_name}, however the local shared secret does not exist.&quot; +
-          &quot; To remedy this, you could delete the registration via webUI/REST, change the node_name option in config.rb&quot; +
-          &quot; (or use the -N/--node-name option to the CLI) or&quot; +
-          &quot; copy the old shared secret to #{File.join(Chef::Config[:file_cache_path], 'registration', @safe_name)}&quot;, 3
+      if File.exists?(Chef::Config[:validation_key])
+        @vr = Chef::REST.new(Chef::Config[:client_url], Chef::Config[:validation_client_name], Chef::Config[:validation_key])
+        @vr.register(@node_name, Chef::Config[:client_key])
+      else
+        Chef::Log.debug(&quot;Validation key #{Chef::Config[:validation_key]} is not present - skipping registration&quot;)
       end
-
+      # We now have the client key, and should use it from now on.
+      @rest = Chef::REST.new(Chef::Config[:chef_server_url])
       true
     end
     
-    # Generates a random secret, stores it in the Chef::Filestore with the &quot;registration&quot; key,
-    # and posts our nodes registration information to the server.
-    #
-    # === Returns
-    # true:: Always returns true
-    def create_registration
-      @secret = random_password(500)
-      Chef::FileCache.store(File.join(&quot;registration&quot;, @safe_name), @secret)
-      @rest.post_rest(&quot;registrations&quot;, { :id =&gt; @safe_name, :password =&gt; @secret, :validation_token =&gt; @validation_token })
-      true
-    end
-    
-    # Authenticates the node via OpenID.
-    #
-    # === Returns
-    # true:: Always returns true
-    def authenticate
-      determine_node_name unless @node_name
-      Chef::Log.debug(&quot;Authenticating #{@safe_name} via openid&quot;) 
-      response = @rest.post_rest('openid/consumer/start', { 
-        &quot;openid_identifier&quot; =&gt; &quot;#{Chef::Config[:openid_url]}/openid/server/node/#{@safe_name}&quot;,
-        &quot;submit&quot; =&gt; &quot;Verify&quot;
-      })
-      @rest.post_rest(
-        &quot;#{Chef::Config[:openid_url]}#{response[&quot;action&quot;]}&quot;,
-        { &quot;password&quot; =&gt; @secret }
-      )
-    end
-    
     # Update the file caches for a given cache segment.  Takes a segment name
     # and a hash that matches one of the cookbooks/_attribute_files style
     # remote file listings.
@@ -253,125 +211,83 @@ class Chef
     # === Parameters
     # segment&lt;String&gt;:: The cache segment to update
     # remote_list&lt;Hash&gt;:: A cookbooks/_attribute_files style remote file listing
-    def update_file_cache(segment, remote_list)  
-      # We need the list of known good attribute files, so we can delete any that are
-      # just laying about.
+    def update_file_cache(cookbook_name, parts)  
+      Chef::Log.debug(&quot;Synchronizing cookbook #{cookbook_name}&quot;)
+
       file_canonical = Hash.new
-      
-      remote_list.each do |rf|
-        cache_file = File.join(&quot;cookbooks&quot;, rf['cookbook'], segment, rf['name'])
-        file_canonical[cache_file] = true
 
-        # For back-compat between older clients and new chef servers
-        rf['checksum'] ||= nil 
-      
-        current_checksum = nil
-        if Chef::FileCache.has_key?(cache_file)
-          current_checksum = checksum(Chef::FileCache.load(cache_file, false))
-        end
+      [ &quot;recipes&quot;, &quot;attributes&quot;, &quot;definitions&quot;, &quot;libraries&quot;, &quot;resources&quot;, &quot;providers&quot; ].each do |segment|
+        remote_list = parts.has_key?(segment) ? parts[segment] : []
 
-        rf_url = generate_cookbook_url(
-          rf['name'], 
-          rf['cookbook'], 
-          segment, 
-          @node, 
-          current_checksum ? { 'checksum' =&gt; current_checksum } : nil
-        )
-        Chef::Log.debug(rf_url)
+        # segement = cookbook segment
+        # remote_list = list of file hashes
+        #
+        # We need the list of known good attribute files, so we can delete any that are
+        # just laying about.
+        
+        remote_list.each do |rf|
+          cache_file = File.join(&quot;cookbooks&quot;, cookbook_name, segment, rf['name'])
+          file_canonical[cache_file] = true
 
-        if current_checksum != rf['checksum']
-          changed = true
-          begin
-            raw_file = @rest.get_rest(rf_url, true)
-          rescue Net::HTTPRetriableError =&gt; e
-            if e.response.kind_of?(Net::HTTPNotModified)
-              changed = false
-              Chef::Log.debug(&quot;Cache file #{cache_file} is unchanged&quot;)
-            else
-              raise e
-            end
+          # For back-compat between older clients and new chef servers
+          rf['checksum'] ||= nil 
+        
+          current_checksum = nil
+          if Chef::FileCache.has_key?(cache_file)
+            current_checksum = checksum(Chef::FileCache.load(cache_file, false))
           end
 
-          if changed
-            Chef::Log.info(&quot;Storing updated #{cache_file} in the cache.&quot;)
-            Chef::FileCache.move_to(raw_file.path, cache_file)
+          rf_url = generate_cookbook_url(
+            rf['name'], 
+            cookbook_name, 
+            segment, 
+            @node, 
+            current_checksum ? { 'checksum' =&gt; current_checksum } : nil
+          )
+          if current_checksum != rf['checksum']
+            changed = true
+            begin
+              raw_file = @rest.get_rest(rf_url, true)
+            rescue Net::HTTPRetriableError =&gt; e
+              if e.response.kind_of?(Net::HTTPNotModified)
+                changed = false
+                Chef::Log.debug(&quot;Cache file #{cache_file} is unchanged&quot;)
+              else
+                raise e
+              end
+            end
+
+            if changed
+              Chef::Log.info(&quot;Storing updated #{cache_file} in the cache.&quot;)
+              Chef::FileCache.move_to(raw_file.path, cache_file)
+            end
           end
         end
-      end
-      
-      Chef::FileCache.list.each do |cache_file|
-        if cache_file.match(&quot;cookbooks/.+?/#{segment}&quot;)
-          unless file_canonical[cache_file]
-            Chef::Log.info(&quot;Removing #{cache_file} from the cache; it is no longer on the server.&quot;)
-            Chef::FileCache.delete(cache_file)
+
+        Chef::FileCache.list.each do |cache_file|
+          if cache_file =~ /^cookbooks\/(recipes|attributes|definitions|libraries)\//
+            unless file_canonical[cache_file]
+              Chef::Log.info(&quot;Removing #{cache_file} from the cache; it is no longer on the server.&quot;)
+              Chef::FileCache.delete(cache_file)
+            end
           end
         end
+
       end
       
     end
-    
-    # Gets all the attribute files included in all the cookbooks available on the server,
-    # and executes them.
-    #
-    # === Returns
-    # true:: Always returns true
-    def sync_attribute_files
-      Chef::Log.debug(&quot;Synchronizing attributes&quot;)
-      update_file_cache(&quot;attributes&quot;, @rest.get_rest(&quot;cookbooks/_attribute_files?node=#{@node.name}&quot;))
-      true
-    end
-    
-    # Gets all the library files included in all the cookbooks available on the server,
-    # and loads them.
-    #
-    # === Returns
-    # true:: Always returns true
-    def sync_library_files
-      Chef::Log.debug(&quot;Synchronizing libraries&quot;)
-      update_file_cache(&quot;libraries&quot;, @rest.get_rest(&quot;cookbooks/_library_files?node=#{@node.name}&quot;))
-      true
-    end
-
-    # Gets all the provider files included in all the cookbooks available on the server,
-    # and loads them.
-    #
-    # === Returns
-    # true:: Always returns true
-    def sync_provider_files
-      Chef::Log.debug(&quot;Synchronizing providers&quot;) 
-      update_file_cache(&quot;providers&quot;, @rest.get_rest(&quot;cookbooks/_provider_files?node=#{@node.name}&quot;))
-      true
-    end
-    
-    # Gets all the resource files included in all the cookbooks available on the server,
-    # and loads them.
-    #
-    # === Returns
-    # true:: Always returns true
-    def sync_resource_files
-      Chef::Log.debug(&quot;Synchronizing resources&quot;)
-      update_file_cache(&quot;resources&quot;, @rest.get_rest(&quot;cookbooks/_resource_files?node=#{@node.name}&quot;))
-      true
-    end
 
-    # Gets all the definition files included in all the cookbooks available on the server,
-    # and loads them.
+    # Synchronizes all the cookbooks from the chef-server.
     #
     # === Returns
     # true:: Always returns true
-    def sync_definitions
-      Chef::Log.debug(&quot;Synchronizing definitions&quot;) 
-      update_file_cache(&quot;definitions&quot;, @rest.get_rest(&quot;cookbooks/_definition_files?node=#{@node.name}&quot;))
-    end
-    
-    # Gets all the recipe files included in all the cookbooks available on the server,
-    # and loads them.
-    #
-    # === Returns
-    # true:: Always returns true
-    def sync_recipes
-      Chef::Log.debug(&quot;Synchronizing recipes&quot;)
-      update_file_cache(&quot;recipes&quot;, @rest.get_rest(&quot;cookbooks/_recipe_files?node=#{@node.name}&quot;))
+    def sync_cookbooks
+      Chef::Log.debug(&quot;Synchronizing cookbooks&quot;)
+      cookbook_hash = @rest.get_rest(&quot;nodes/#{@safe_name}/cookbooks&quot;)
+      Chef::Log.debug(&quot;Cookbooks to load: #{cookbook_hash.inspect}&quot;)
+      cookbook_hash.each do |cookbook_name, parts|
+        update_file_cache(cookbook_name, parts)
+      end
     end
     
     # Updates the current node configuration on the server.
@@ -407,15 +323,6 @@ class Chef
       cr.converge
       true
     end
-        
-    protected
-      # Generates a random password of &quot;len&quot; length.
-      def random_password(len)
-        chars = (&quot;a&quot;..&quot;z&quot;).to_a + (&quot;A&quot;..&quot;Z&quot;).to_a + (&quot;0&quot;..&quot;9&quot;).to_a
-        newpass = &quot;&quot;
-        1.upto(len) { |i| newpass &lt;&lt; chars[rand(chars.size-1)] }
-        newpass
-      end
 
   end
 end</diff>
      <filename>chef/lib/chef/client.rb</filename>
    </modified>
    <modified>
      <diff>@@ -17,6 +17,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+require 'chef/log'
 require 'mixlib/config'
 
 class Chef
@@ -54,13 +55,24 @@ class Chef
           :template_url,
           :remotefile_url,
           :search_url,
+          :chef_server_url,
           :role_url ].each do |u| 
             c[u] = url
         end
       end
       url
     end
-    
+
+    # When you are using ActiveSupport, they monkey-patch 'daemonize' into Kernel.  
+    # So while this is basically identical to what method_missing would do, we pull
+    # it up here and get a real method written so that things get dispatched 
+    # properly.
+    config_attr_writer :daemonize do |v|
+      configure do |c|
+        c[:daemonize] = v
+      end
+    end
+
     # Override the config dispatch to set the value of log_location configuration option
     #
     # === Parameters
@@ -86,12 +98,10 @@ class Chef
 
     authorized_openid_identifiers nil
     authorized_openid_providers nil
-    chef_server_url nil
     cookbook_path [ &quot;/var/chef/site-cookbooks&quot;, &quot;/var/chef/cookbooks&quot; ]
     couchdb_database &quot;chef&quot;
     couchdb_url &quot;http://localhost:5984&quot;
     couchdb_version nil
-    daemonize nil
     delay 0
     executable_path ENV['PATH'] ? ENV['PATH'].split(File::PATH_SEPARATOR) : []
     file_cache_path &quot;/var/chef/cache&quot;
@@ -118,8 +128,9 @@ class Chef
     queue_retry_count 5
     queue_retry_delay 5
     queue_user &quot;&quot;
-    queue_prefix nil
+    chef_server_url &quot;http://localhost:4000&quot;
     registration_url &quot;http://localhost:4000&quot;
+    client_url &quot;http://localhost:4042&quot;
     remotefile_url &quot;http://localhost:4000&quot;
     rest_timeout 60
     run_command_stderr_timeout 120
@@ -137,5 +148,37 @@ class Chef
     role_path &quot;/var/chef/roles&quot;
     role_url &quot;http://localhost:4000&quot;
     recipe_url nil
+    solr_url &quot;http://localhost:8983&quot;
+    solr_jetty_path &quot;/var/chef/solr-jetty&quot;
+    solr_data_path &quot;/var/chef/solr/data&quot;
+    solr_home_path &quot;/var/chef/solr&quot;
+    solr_heap_size &quot;256M&quot;
+    solr_java_opts nil
+    nanite_host '0.0.0.0'
+    nanite_port '5672'
+    nanite_user 'nanite'
+    nanite_pass 'testing'
+    nanite_vhost '/nanite'
+    nanite_identity nil
+    nanite_persistent_mapper false
+
+    client_key &quot;/etc/chef/client.pem&quot;
+    validation_key &quot;/etc/chef/validation.pem&quot;
+    validation_client_name &quot;chef-validator&quot;
+    web_ui_client_name &quot;chef-webui&quot;
+    web_ui_key &quot;/etc/chef/webui.pem&quot;
+
+    # Server Signing CA
+    #
+    # In truth, these don't even have to change
+    signing_ca_cert &quot;/var/chef/ca/cert.pem&quot;
+    signing_ca_key &quot;/var/chef/ca/key.pem&quot;
+    signing_ca_country &quot;US&quot;
+    signing_ca_state &quot;Washington&quot;
+    signing_ca_location &quot;Seattle&quot;
+    signing_ca_org &quot;Chef User&quot;
+    signing_ca_domain &quot;opensource.opscode.com&quot;
+    signing_ca_email &quot;opensource-cert@opscode.com&quot;
+
   end
 end</diff>
      <filename>chef/lib/chef/config.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,6 @@
 #
 # Author:: Adam Jacob (&lt;adam@opscode.com&gt;)
+# Author:: Nuo Yan (&lt;nuo@opscode.com&gt;)
 # Author:: Christopher Walters (&lt;cw@opscode.com&gt;)
 # Copyright:: Copyright (c) 2008 Opscode, Inc.
 # License:: Apache License, Version 2.0</diff>
      <filename>chef/lib/chef/cookbook.rb</filename>
    </modified>
    <modified>
      <diff>@@ -379,6 +379,7 @@ class Chef
         self.maintainer o['maintainer'] if o.has_key?('maintainer')
         self.maintainer_email o['maintainer_email'] if o.has_key?('maintainer_email')
         self.license o['license'] if o.has_key?('license')
+        self.version o['version'] if o.has_key?('version')
         self.platforms = o['platforms'] if o.has_key?('platforms')
         self.dependencies = o['dependencies'] if o.has_key?('dependencies')
         self.recommendations = o['recommendations'] if o.has_key?('recommendations')</diff>
      <filename>chef/lib/chef/cookbook/metadata.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,40 +21,82 @@ require 'chef/rest'
 require 'chef/log'
 require 'digest/sha2'
 require 'json'
+require 'chef/nanite'
+
+# We want to fail on create if uuidtools isn't installed
+begin
+  require 'uuidtools'
+rescue LoadError
+end
 
 class Chef
   class CouchDB
     include Chef::Mixin::ParamsValidate
 
-    def initialize(url=nil)
+    def initialize(url=nil, db=Chef::Config[:couchdb_database])
       url ||= Chef::Config[:couchdb_url]
-      @rest = Chef::REST.new(url)
+      @db = db
+      @rest = Chef::REST.new(url, nil, nil)
     end
-    
+
+    def couchdb_database(args=nil)
+      if args
+        @db = args
+      else
+        @db
+      end
+    end
+
+    def create_id_map
+      create_design_document(
+        &quot;id_map&quot;, 
+        {
+          &quot;version&quot; =&gt; 1,
+          &quot;language&quot; =&gt; &quot;javascript&quot;,
+          &quot;views&quot; =&gt; {
+            &quot;name_to_id&quot; =&gt; {
+              &quot;map&quot; =&gt; &lt;&lt;-EOJS
+                function(doc) {
+                  emit([ doc.chef_type, doc.name], doc._id);
+                }
+              EOJS
+            },
+            &quot;id_to_name&quot; =&gt; {
+              &quot;map&quot; =&gt; &lt;&lt;-EOJS
+                function(doc) { 
+                  emit(doc._id, [ doc.chef_type, doc.name ]);
+                }
+              EOJS
+            }
+          }
+        }
+      )
+    end
+
     def create_db
       @database_list = @rest.get_rest(&quot;_all_dbs&quot;)
-      unless @database_list.detect { |db| db == Chef::Config[:couchdb_database] }
-        response = @rest.put_rest(Chef::Config[:couchdb_database], Hash.new)
+      unless @database_list.detect { |db| db == couchdb_database }
+        response = @rest.put_rest(couchdb_database, Hash.new)
       end
-      Chef::Config[:couchdb_database]
+      couchdb_database
     end
     
     def create_design_document(name, data)
       create_db
       to_update = true
       begin
-        old_doc = @rest.get_rest(&quot;#{Chef::Config[:couchdb_database]}/_design%2F#{name}&quot;)
+        old_doc = @rest.get_rest(&quot;#{couchdb_database}/_design/#{name}&quot;)
         if data[&quot;version&quot;] != old_doc[&quot;version&quot;]
           data[&quot;_rev&quot;] = old_doc[&quot;_rev&quot;]
           Chef::Log.debug(&quot;Updating #{name} views&quot;)
         else
           to_update = false
         end
-      rescue
-        Chef::Log.debug(&quot;Creating #{name} views for the first time&quot;)
+      rescue 
+        Chef::Log.debug(&quot;Creating #{name} views for the first time because: #{$!}&quot;)
       end
       if to_update
-        @rest.put_rest(&quot;#{Chef::Config[:couchdb_database]}/_design%2F#{name}&quot;, data)
+        @rest.put_rest(&quot;#{couchdb_database}/_design%2F#{name}&quot;, data)
       end
       true
     end
@@ -70,7 +112,27 @@ class Chef
           :object =&gt; { :respond_to =&gt; :to_json },
         }
       )
-      @rest.put_rest(&quot;#{Chef::Config[:couchdb_database]}/#{obj_type}_#{safe_name(name)}&quot;, object)
+      r = get_view(&quot;id_map&quot;, &quot;name_to_id&quot;, :key =&gt; [ obj_type, name ])
+      uuid = nil
+      if r[&quot;rows&quot;].length == 1
+        uuid = r[&quot;rows&quot;][0][&quot;id&quot;]
+      else
+        uuid = UUIDTools::UUID.random_create.to_s
+      end
+        
+      r = @rest.put_rest(&quot;#{couchdb_database}/#{uuid}&quot;, object)
+      Chef::Log.info(&quot;Sending #{uuid} to Nanite for indexing..&quot;)
+      n = Chef::Nanite.push(
+        &quot;/index/add&quot;,
+        { 
+          :id =&gt; uuid,
+          :database =&gt; couchdb_database,
+          :type =&gt; obj_type,
+          :item =&gt; object
+        },
+        :persistent =&gt; true
+      )
+      r
     end
 
     def load(obj_type, name)
@@ -84,7 +146,9 @@ class Chef
           :name =&gt; { :kind_of =&gt; String },
         }
       )
-      @rest.get_rest(&quot;#{Chef::Config[:couchdb_database]}/#{obj_type}_#{safe_name(name)}&quot;)
+      doc = find_by_name(obj_type, name)
+      doc.couchdb = self if doc.respond_to?(:couchdb)
+      doc 
     end
   
     def delete(obj_type, name, rev=nil)
@@ -98,15 +162,28 @@ class Chef
           :name =&gt; { :kind_of =&gt; String },
         }
       )
+      del_id = nil 
+      last_obj, obj_id = find_by_name(obj_type, name, true)
       unless rev
-        last_obj = @rest.get_rest(&quot;#{Chef::Config[:couchdb_database]}/#{obj_type}_#{safe_name(name)}&quot;)
         if last_obj.respond_to?(:couchdb_rev)
           rev = last_obj.couchdb_rev
         else
           rev = last_obj['_rev']
         end
       end
-      @rest.delete_rest(&quot;#{Chef::Config[:couchdb_database]}/#{obj_type}_#{safe_name(name)}?rev=#{rev}&quot;)
+      r = @rest.delete_rest(&quot;#{couchdb_database}/#{obj_id}?rev=#{rev}&quot;)
+      r.couchdb = self if r.respond_to?(:couchdb)
+      Chef::Log.info(&quot;Sending #{obj_id} to Nanite for deletion..&quot;)
+      n = Chef::Nanite.push(
+        &quot;/index/delete&quot;,
+        { 
+          :id =&gt; obj_id,
+          :database =&gt; couchdb_database,
+          :type =&gt; obj_type
+        },
+        :persistent =&gt; true
+      )
+      r
     end
   
     def list(view, inflate=false)
@@ -119,10 +196,13 @@ class Chef
         }
       )
       if inflate
-        @rest.get_rest(view_uri(view, &quot;all&quot;))
+        r = @rest.get_rest(view_uri(view, &quot;all&quot;))
+        r[&quot;rows&quot;].each { |i| i[&quot;value&quot;].couchdb = self if i[&quot;value&quot;].respond_to?(:couchdb=) }
+        r
       else
-        @rest.get_rest(view_uri(view, &quot;all_id&quot;))
+        r = @rest.get_rest(view_uri(view, &quot;all_id&quot;))
       end
+      r
     end
   
     def has_key?(obj_type, name)
@@ -137,13 +217,25 @@ class Chef
         }
       )
       begin
-        @rest.get_rest(&quot;#{Chef::Config[:couchdb_database]}/#{obj_type}_#{safe_name(name)}&quot;)
+        find_by_name(obj_type, name)
         true
       rescue
         false
       end
     end
 
+    def find_by_name(obj_type, name, with_id=false)
+      r = get_view(&quot;id_map&quot;, &quot;name_to_id&quot;, :key =&gt; [ obj_type, name ], :include_docs =&gt; true)
+      if r[&quot;rows&quot;].length == 0
+        raise Chef::Exceptions::CouchDBNotFound, &quot;Cannot find #{obj_type} #{name} in CouchDB!&quot;
+      end
+      if with_id
+        [ r[&quot;rows&quot;][0][&quot;doc&quot;], r[&quot;rows&quot;][0][&quot;id&quot;] ]
+      else
+        r[&quot;rows&quot;][0][&quot;doc&quot;] 
+      end
+    end
+
     def get_view(design, view, options={})
       view_string = view_uri(design, view)
       view_string &lt;&lt; &quot;?&quot; if options.length != 0
@@ -151,18 +243,23 @@ class Chef
       options.each { |k,v| view_string &lt;&lt; &quot;#{first ? '' : '&amp;'}#{k}=#{URI.escape(v.to_json)}&quot;; first = false }
       @rest.get_rest(view_string)
     end
+
+    def bulk_get(*to_fetch)
+      response = @rest.post_rest(&quot;#{couchdb_database}/_all_docs?include_docs=true&quot;, { &quot;keys&quot; =&gt; to_fetch.flatten })
+      response[&quot;rows&quot;].collect { |r| r[&quot;doc&quot;] }
+    end
     
     def view_uri(design, view)
       Chef::Config[:couchdb_version] ||= @rest.run_request(:GET,
                                                            URI.parse(@rest.url + &quot;/&quot;),
-                                                           false,
+                                                           {},
                                                            10,
                                                            false)[&quot;version&quot;].gsub(/-.+/,&quot;&quot;).to_f
       case Chef::Config[:couchdb_version]
       when 0.8
-        &quot;#{Chef::Config[:couchdb_database]}/_view/#{design}/#{view}&quot;
+        &quot;#{couchdb_database}/_view/#{design}/#{view}&quot;
       else
-        &quot;#{Chef::Config[:couchdb_database]}/_design/#{design}/_view/#{view}&quot;
+        &quot;#{couchdb_database}/_design/#{design}/_view/#{view}&quot;
       end
     end
     
@@ -171,6 +268,6 @@ class Chef
       def safe_name(name)
         name.gsub(/\./, &quot;_&quot;)
       end
-      
+
   end
 end</diff>
      <filename>chef/lib/chef/couchdb.rb</filename>
    </modified>
    <modified>
      <diff>@@ -32,5 +32,8 @@ class Chef
     class Group &lt; RuntimeError; end
     class Link &lt; RuntimeError; end
     class Mount &lt; RuntimeError; end
+    class CouchDBNotFound &lt; RuntimeError; end
+    class PrivateKeyMissing &lt; RuntimeError; end
+    class CannotWritePrivateKey &lt; RuntimeError; end
   end
 end</diff>
      <filename>chef/lib/chef/exceptions.rb</filename>
    </modified>
    <modified>
      <diff>@@ -74,6 +74,8 @@ class Chef
         ]
         
         file_list_str = file_list.keys.join(&quot;\n&quot;)
+        Chef::Log.debug(&quot;Searching for preferred file in\n#{file_list_str}&quot;)
+        
         preferences.each do |pref|
           Chef::Log.debug(&quot;Looking for #{pref}&quot;)
           matcher = /^(.+#{pref})$/</diff>
      <filename>chef/lib/chef/mixin/find_preferred_file.rb</filename>
    </modified>
    <modified>
      <diff>@@ -30,19 +30,28 @@ class Chef
         else
           new_url = &quot;cookbooks/#{cookbook}/#{type}?&quot;
           new_url += &quot;id=#{url}&quot;
-          platform, version = Chef::Platform.find_platform_and_version(node)
-          if type == &quot;files&quot; || type == &quot;templates&quot;
-            new_url += &quot;&amp;platform=#{platform}&amp;version=#{version}&amp;fqdn=#{node[:fqdn]}&amp;node_name=#{node.name}&quot;
-          end
-          if args
-            args.each do |key, value|
-              new_url += &quot;&amp;#{key}=#{value}&quot;
-            end
-          end
+          new_url = generate_cookbook_url_from_uri(new_url, node, args)
         end
         Chef::Log.debug(&quot;generated cookbook url: #{new_url}&quot;)
         return new_url
       end
+
+      def generate_cookbook_url_from_uri(uri, node, args=nil)
+        platform, version = Chef::Platform.find_platform_and_version(node)
+        uri =~ /cookbooks\/(.+?)\/(.+)\?/
+        cookbook = $1
+        type = $2
+        if type == &quot;files&quot; || type == &quot;templates&quot;
+          uri += &quot;&amp;platform=#{platform}&amp;version=#{version}&amp;fqdn=#{node[:fqdn]}&amp;node_name=#{node.name}&quot;
+        end
+        if args
+          args.each do |key, value|
+            uri += &quot;&amp;#{key}=#{value}&quot;
+          end
+        end
+
+        uri
+      end
       
     end
   end</diff>
      <filename>chef/lib/chef/mixin/generate_url.rb</filename>
    </modified>
    <modified>
      <diff>@@ -16,6 +16,8 @@
 # limitations under the License.
 #
 
+require 'chef/search/query'
+
 class Chef
   module Mixin
     module Language
@@ -73,6 +75,10 @@ class Chef
   
         has_platform
       end
+
+      def search(*args, &amp;block)
+        Chef::Search::Query.new.search(*args, &amp;block)
+      end
       
     end
   end</diff>
      <filename>chef/lib/chef/mixin/language.rb</filename>
    </modified>
    <modified>
      <diff>@@ -20,12 +20,14 @@
 require 'chef/recipe'
 require 'chef/resource'
 require 'chef/mixin/convert_to_class_name'
+require 'chef/mixin/language'
 
 class Chef
   module Mixin
     module RecipeDefinitionDSLCore
       
       include Chef::Mixin::ConvertToClassName
+      include Chef::Mixin::Language
       
       def method_missing(method_symbol, *args, &amp;block)
         # If we have a definition that matches, we want to use that instead.  This should</diff>
      <filename>chef/lib/chef/mixin/recipe_definition_dsl_core.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,7 +21,7 @@ require 'chef/mixin/check_helper'
 require 'chef/mixin/params_validate'
 require 'chef/mixin/from_file'
 require 'chef/couchdb'
-require 'chef/queue'
+require 'chef/rest'
 require 'chef/run_list'
 require 'chef/node/attribute'
 require 'extlib'
@@ -30,14 +30,14 @@ require 'json'
 class Chef
   class Node
     
-    attr_accessor :attribute, :recipe_list, :couchdb_rev, :run_state, :run_list, :override, :default
+    attr_accessor :attribute, :recipe_list, :couchdb_rev, :couchdb_id, :run_state, :run_list, :override, :default
     
     include Chef::Mixin::CheckHelper
     include Chef::Mixin::FromFile
     include Chef::Mixin::ParamsValidate
     
     DESIGN_DOCUMENT = {
-      &quot;version&quot; =&gt; 8,
+      &quot;version&quot; =&gt; 9,
       &quot;language&quot; =&gt; &quot;javascript&quot;,
       &quot;views&quot; =&gt; {
         &quot;all&quot; =&gt; {
@@ -120,7 +120,7 @@ class Chef
     }
     
     # Create a new Chef::Node object.
-    def initialize()
+    def initialize
       @name = nil
 
       @attribute = Mash.new
@@ -129,7 +129,9 @@ class Chef
       @run_list = Chef::RunList.new 
 
       @couchdb_rev = nil
+      @couchdb_id = nil
       @couchdb = Chef::CouchDB.new
+
       @run_state = {
         :template_cache =&gt; Hash.new,
         :seen_recipes =&gt; Hash.new
@@ -281,53 +283,17 @@ class Chef
       @run_list.detect { |r| r == item } ? true : false
     end
     
-    # Turns the node into an object that we can index.  I apologize up front for the
-    # super confusion that is the recursive index_flatten hash, which comes up next.
-    # Faith, young one, faith.
-    #
-    # === Returns
-    # index_hash&lt;Hash&gt;:: A flattened hash of all the nodes attributes, suitable for indexing.
-    def to_index
-      index_hash = {
-        &quot;index_name&quot; =&gt; &quot;node&quot;,
-        &quot;id&quot; =&gt; &quot;node_#{@name}&quot;,
-        &quot;name&quot; =&gt; @name,
-      }
-      @attribute.each do |key, value|
-        if value.kind_of?(Hash) || value.kind_of?(Mash)
-          index_flatten_hash(key, value).each do |to_index|
-            to_index.each do |nk, nv|
-              index_hash[nk] = nv
-            end
-          end
-        else
-          index_hash[key] = value
-        end
-      end
-      index_hash[&quot;recipe&quot;] = @run_list.recipes if @run_list.recipes.length &gt; 0
+    # Transform the node to a Hash
+    def to_hash
+      index_hash = @attribute
+      index_hash[&quot;chef_type&quot;] = &quot;node&quot;
+      index_hash[&quot;name&quot;] = @name
+      index_hash[&quot;recipes&quot;] = @run_list.recipes if @run_list.recipes.length &gt; 0
       index_hash[&quot;roles&quot;] = @run_list.roles if @run_list.roles.length &gt; 0
       index_hash[&quot;run_list&quot;] = @run_list.run_list if @run_list.run_list.length &gt; 0
       index_hash
     end
     
-    # Ah, song of my heart, index_flatten_hash.  This method flattens a hash in preparation
-    # for indexing, by appending the name of it's parent to a current key with an _.  Hence,
-    # node[:bar][:baz] = 'monkey' becomes bar_baz:monkey.
-    #
-    # === Returns
-    # results&lt;Array&gt;:: An array of hashes with one element.
-    def index_flatten_hash(parent_name, hash)
-      results = Array.new
-      hash.each do |k, v|
-        if v.kind_of?(Hash) || v.kind_of?(Mash)
-          results &lt;&lt; index_flatten_hash(&quot;#{parent_name}_#{k}&quot;, v)
-        else
-          results &lt;&lt; { &quot;#{parent_name}_#{k}&quot;, v }
-        end
-      end
-      results.flatten
-    end
-    
     # Serialize this object as a hash 
     def to_json(*a)
       result = {
@@ -360,47 +326,103 @@ class Chef
         o[&quot;recipes&quot;].each { |r| node.recipes &lt;&lt; r }
       end
       node.couchdb_rev = o[&quot;_rev&quot;] if o.has_key?(&quot;_rev&quot;)
+      node.couchdb_id = o[&quot;_id&quot;] if o.has_key?(&quot;_id&quot;)
       node
     end
     
     # List all the Chef::Node objects in the CouchDB.  If inflate is set to true, you will get
     # the full list of all Nodes, fully inflated.
-    def self.list(inflate=false)
-      rs = Chef::CouchDB.new.list(&quot;nodes&quot;, inflate)
+    def self.cdb_list(inflate=false)
+      couchdb = Chef::CouchDB.new
+      rs = couchdb.list(&quot;nodes&quot;, inflate)
       if inflate
         rs[&quot;rows&quot;].collect { |r| r[&quot;value&quot;] }
       else
         rs[&quot;rows&quot;].collect { |r| r[&quot;key&quot;] }
       end
     end
+
+    def self.list(inflate=false)
+      r = Chef::REST.new(Chef::Config[:chef_server_url])
+      if inflate
+        response = Hash.new
+        Chef::Search::Query.new.search(:node) do |n|
+          response[n.name] = n
+        end
+        response
+      else
+        r.get_rest(&quot;nodes&quot;)
+      end
+    end
     
     # Load a node by name from CouchDB
+    def self.cdb_load(name)
+      couchdb = Chef::CouchDB.new
+      couchdb.load(&quot;node&quot;, name)
+    end
+
+    # Load a node by name
     def self.load(name)
-      Chef::CouchDB.new.load(&quot;node&quot;, name)
+      r = Chef::REST.new(Chef::Config[:chef_server_url])
+      r.get_rest(&quot;nodes/#{escape_node_id(name)}&quot;)
     end
     
     # Remove this node from the CouchDB
-    def destroy
-      Chef::Queue.send_msg(:queue, :remove, self)
+    def cdb_destroy
       @couchdb.delete(&quot;node&quot;, @name, @couchdb_rev)
     end
+
+    # Remove this node via the REST API
+    def destroy
+      r = Chef::REST.new(Chef::Config[:chef_server_url])
+      r.delete_rest(&quot;nodes/#{Chef::Node.escape_node_id(@name)}&quot;)
+    end
     
     # Save this node to the CouchDB
-    def save
-      Chef::Queue.send_msg(:queue, :index, self)
+    def cdb_save
       results = @couchdb.store(&quot;node&quot;, @name, self)
       @couchdb_rev = results[&quot;rev&quot;]
     end
+
+    # Save this node via the REST API
+    def save
+      r = Chef::REST.new(Chef::Config[:chef_server_url])
+      begin
+        r.put_rest(&quot;nodes/#{Chef::Node.escape_node_id(@name)}&quot;, self)
+      rescue Net::HTTPServerException =&gt; e
+        if e.response.code == &quot;404&quot;
+          r.post_rest(&quot;nodes&quot;, self)
+        else
+          raise e
+        end
+      end
+      self
+    end
     
+    # Create the node via the REST API
+    def create
+      r = Chef::REST.new(Chef::Config[:chef_server_url])
+      r.post_rest(&quot;nodes&quot;, self)
+      self
+    end 
+
     # Set up our CouchDB design document
     def self.create_design_document
-      Chef::CouchDB.new.create_design_document(&quot;nodes&quot;, DESIGN_DOCUMENT)
+      couchdb = Chef::CouchDB.new
+      couchdb.create_design_document(&quot;nodes&quot;, DESIGN_DOCUMENT)
     end
     
     # As a string
     def to_s
       &quot;node[#{@name}]&quot;
     end
+
+    private
+   
+      def self.escape_node_id(arg=nil)
+        arg.gsub(/\./, '_')
+      end
+
     
   end
 end</diff>
      <filename>chef/lib/chef/node.rb</filename>
    </modified>
    <modified>
      <diff>@@ -178,4 +178,4 @@ class Chef
       end
     
   end
-end
\ No newline at end of file
+end</diff>
      <filename>chef/lib/chef/openid_registration.rb</filename>
    </modified>
    <modified>
      <diff>@@ -142,7 +142,6 @@ class Chef
         if pmap.has_key?(rtkey)
           pmap[rtkey]
         else
-          Chef::Log.error(&quot;#{rtkey.inspect} #{pmap.inspect}&quot;)
           raise(
             ArgumentError, 
             &quot;Cannot find a provider for #{resource_type} on #{platform} version #{version}&quot;</diff>
      <filename>chef/lib/chef/platform.rb</filename>
    </modified>
    <modified>
      <diff>@@ -129,7 +129,6 @@ class Chef
 
           status = popen4(&quot;crontab -u #{@new_resource.user} -&quot;, :waitlast =&gt; true) do |pid, stdin, stdout, stderr|
             crontab.each { |line| stdin.puts &quot;#{line}&quot; }
-            stdin.close rescue nil
           end
           Chef::Log.info(&quot;Updated cron '#{@new_resource.name}'&quot;)
           @new_resource.updated = true
@@ -144,7 +143,6 @@ class Chef
 
           status = popen4(&quot;crontab -u #{@new_resource.user} -&quot;, :waitlast =&gt; true) do |pid, stdin, stdout, stderr|
             crontab.each { |line| stdin.puts &quot;#{line}&quot; }
-            stdin.close rescue nil
           end
           Chef::Log.info(&quot;Added cron '#{@new_resource.name}'&quot;)
           @new_resource.updated = true
@@ -175,7 +173,6 @@ class Chef
 
           status = popen4(&quot;crontab -u #{@new_resource.user} -&quot;, :waitlast =&gt; true) do |pid, stdin, stdout, stderr|
             crontab.each { |line| stdin.puts &quot;#{line}&quot; }
-            stdin.close rescue nil
           end
           Chef::Log.debug(&quot;Deleted cron '#{@new_resource.name}'&quot;)
           @new_resource.updated = true</diff>
      <filename>chef/lib/chef/provider/cron.rb</filename>
    </modified>
    <modified>
      <diff>@@ -61,9 +61,15 @@ class Chef
       
       def action_deploy
         if all_releases.include?(release_path)
-          Chef::Log.info(&quot;Already deployed app at #{release_path}, skipping. Use action :force_deploy to force.&quot;)
+          if all_releases[-1] == release_path
+            Chef::Log.debug(&quot;Already deployed app at #{release_path}, and it is the latest revision.  Use action :force_deploy to re-deploy this revision.&quot;)
+          else
+            Chef::Log.info(&quot;Already deployed app at #{release_path}.  Rolling back to it - use action :force_deploy to re-checkout this revision.&quot;)
+            action_rollback
+          end
         else
           deploy
+          @new_resource.updated = true
         end
       end
       
@@ -73,18 +79,31 @@ class Chef
           FileUtils.rm_rf(release_path)
         end
         deploy
+        @new_resource.updated = true
       end
       
       def action_rollback
-        @release_path = all_releases[-2]
-        raise RuntimeError, &quot;There is no release to rollback to!&quot; unless @release_path
-        release_to_nuke = all_releases.last
+        if release_path
+          rp_index = all_releases.index(release_path)
+          raise RuntimeError, &quot;There is no release to rollback to!&quot; unless rp_index
+          rp_index += 1
+          releases_to_nuke = all_releases[rp_index..-1]
+        else
+          @release_path = all_releases[-2] 
+          raise RuntimeError, &quot;There is no release to rollback to!&quot; unless @release_path
+          releases_to_nuke = [ all_releases.last ]
+        end
+
         Chef::Log.info &quot;rolling back to previous release: #{release_path}&quot;
         symlink
-        Chef::Log.info &quot;removing last release: #{release_to_nuke}&quot;
-        FileUtils.rm_rf release_to_nuke
         Chef::Log.info &quot;restarting with previous release&quot;
         restart
+        releases_to_nuke.each do |i|
+          Chef::Log.info &quot;Removing release: #{i}&quot;
+          FileUtils.rm_rf i 
+          release_deleted(i)
+        end
+        @new_resource.updated = true
       end
       
       def deploy
@@ -167,7 +186,7 @@ class Chef
       end
       
       def all_releases
-        Dir.glob(@new_resource.deploy_to + &quot;/releases/*&quot;)
+        Dir.glob(@new_resource.deploy_to + &quot;/releases/*&quot;).sort
       end
       
       def update_cached_repo</diff>
      <filename>chef/lib/chef/provider/deploy.rb</filename>
    </modified>
    <modified>
      <diff>@@ -39,11 +39,13 @@ class Chef
         clone
         checkout
         enable_submodules
+        @new_resource.updated = true
       end
       
       def action_export
         action_checkout
         FileUtils.rm_rf(::File.join(@new_resource.destination,&quot;.git&quot;))
+        @new_resource.updated = true
       end
       
       def action_sync
@@ -53,6 +55,8 @@ class Chef
           sync
           enable_submodules
         end
+
+        @new_resource.updated = true
       end
       
       def find_current_revision
@@ -191,4 +195,4 @@ class Chef
       
     end
   end
-end
\ No newline at end of file
+end</diff>
      <filename>chef/lib/chef/provider/git.rb</filename>
    </modified>
    <modified>
      <diff>@@ -25,7 +25,7 @@ class Chef
       attr_accessor :rest
       
       def load_current_resource
-        @rest = Chef::REST.new(@new_resource.url)
+        @rest = Chef::REST.new(@new_resource.url, nil, nil)
       end
       
       # Send a GET request to @new_resource.url, with ?message=@new_resource.message
@@ -34,6 +34,7 @@ class Chef
         body = @rest.run_request(
           :GET, 
           @rest.create_url(&quot;#{@new_resource.url}?message=#{message}&quot;),
+          {},
           false,
           10,
           false
@@ -49,6 +50,7 @@ class Chef
         body = @rest.run_request(
           :PUT,
           @rest.create_url(&quot;#{@new_resource.url}&quot;),
+          {},
           message,
           10,
           false
@@ -64,6 +66,7 @@ class Chef
         body = @rest.run_request(
           :POST,
           @rest.create_url(&quot;#{@new_resource.url}&quot;),
+          {},
           message,
           10,
           false
@@ -78,6 +81,7 @@ class Chef
         body = @rest.run_request(
           :DELETE,
           @rest.create_url(&quot;#{@new_resource.url}&quot;),
+          {},
           false,
           10,
           false
@@ -99,4 +103,4 @@ class Chef
       
     end
   end
-end
\ No newline at end of file
+end</diff>
      <filename>chef/lib/chef/provider/http_request.rb</filename>
    </modified>
    <modified>
      <diff>@@ -38,7 +38,7 @@ class Chef
 
           if( ::File.exists?(catdir) )
             Dir.entries(catdir).each do |entry|
-              if(entry =~ /^#{Regexp.escape(pkg)}\-(\d[\.\d]*((_(alpha|beta|pre|rc|p)\d*)*)?)/)
+              if(entry =~ /^#{Regexp.escape(pkg)}\-(\d[\.\d]*((_(alpha|beta|pre|rc|p)\d*)*)?(-r\d+)?)/)
                 @current_resource.version($1)
                 Chef::Log.debug(&quot;Got current version #{$1}&quot;)
                 break</diff>
      <filename>chef/lib/chef/provider/package/portage.rb</filename>
    </modified>
    <modified>
      <diff>@@ -34,6 +34,8 @@ import yum
 
 from yum import Errors
 
+PIDFILE='/var/run/yum.pid'
+
 # Seconds to wait for exclusive access to yum
 lock_timeout = 10
 
@@ -54,7 +56,7 @@ try:
     countdown = lock_timeout
     while True:
       try:
-        y.doLock()
+        y.doLock(PIDFILE)
       except Errors.LockError, e:
         time.sleep(1)
         countdown -= 1 
@@ -80,7 +82,7 @@ try:
 # Ensure we clear the lock.
 finally:
   try:
-    y.doUnlock()
+    y.doUnlock(PIDFILE)
   # Keep Unlock from raising a second exception as it does with a yum.conf 
   # config error.
   except Errors.YumBaseError:</diff>
      <filename>chef/lib/chef/provider/package/yum-dump.py</filename>
    </modified>
    <modified>
      <diff>@@ -102,7 +102,7 @@ class Chef
         begin
           uri = URI.parse(source)
           if uri.absolute
-            r = Chef::REST.new(source)
+            r = Chef::REST.new(source, nil, nil)
             Chef::Log.debug(&quot;Downloading from absolute URI: #{source}&quot;)
             r.get_rest(source, true).open
           end</diff>
      <filename>chef/lib/chef/provider/remote_file.rb</filename>
    </modified>
    <modified>
      <diff>@@ -70,7 +70,6 @@ class Chef
             end
 
             status = popen4(@node[:command][:ps]) do |pid, stdin, stdout, stderr|
-              stdin.close rescue nil
               r = Regexp.new(@new_resource.pattern)
               Chef::Log.debug(&quot;#{@new_resource}: attempting to match #{@new_resource.pattern} (#{r}) against process table&quot;)
               stdout.each_line do |line|</diff>
      <filename>chef/lib/chef/provider/service/freebsd.rb</filename>
    </modified>
    <modified>
      <diff>@@ -55,7 +55,6 @@ class Chef
               raise Chef::Exceptions::Service, &quot;#{@new_resource}: could not determine how to inspect the process table, please set this nodes 'command.ps' attribute&quot;
             end
             status = popen4(@node[:command][:ps]) do |pid, stdin, stdout, stderr|
-              stdin.close rescue nil
               r = Regexp.new(@new_resource.pattern)
               Chef::Log.warn &quot;#{@new_resource}: attempting to match '#{@new_resource.pattern}' (#{r}) against process list&quot;
               stdout.each_line do |line|</diff>
      <filename>chef/lib/chef/provider/service/simple.rb</filename>
    </modified>
    <modified>
      <diff>@@ -37,10 +37,12 @@ class Chef
       
       def action_checkout
         run_command(run_options(:command =&gt; checkout_command))
+        @new_resource.updated = true
       end
       
       def action_export
         run_command(run_options(:command =&gt; export_command))
+        @new_resource.updated = true
       end
       
       def action_sync
@@ -49,6 +51,7 @@ class Chef
         else
           run_command(run_options(:command =&gt; sync_command))
         end
+        @new_resource.updated = true
       end
       
       def sync_command</diff>
      <filename>chef/lib/chef/provider/subversion.rb</filename>
    </modified>
    <modified>
      <diff>@@ -34,7 +34,6 @@ class Chef
       include Chef::Mixin::FindPreferredFile
       
       def action_create
-        Chef::Log.debug(@node.run_state.inspect)
         raw_template_file = nil
         
         cookbook_name = @new_resource.cookbook || @new_resource.cookbook_name</diff>
      <filename>chef/lib/chef/provider/template.rb</filename>
    </modified>
    <modified>
      <diff>@@ -25,7 +25,6 @@ require 'chef/mixin/recipe_definition_dsl_core'
 require 'chef/resource_collection'
 require 'chef/cookbook_loader'
 require 'chef/rest'
-require 'chef/search/result'
 
 class Chef
   class Recipe
@@ -76,21 +75,6 @@ class Chef
       @collection.resources(*args)
     end
     
-    def search(type, query, attributes=[], &amp;block)
-      Chef::Log.debug(&quot;Searching #{type} index with #{query}&quot;)
-      r = Chef::REST.new(Chef::Config[:search_url])
-
-      results = r.get_rest(&quot;search/#{type}?q=#{query}&amp;a=#{attributes.join(',')}&quot;)
-      Chef::Log.debug(&quot;Searching #{type} index with #{query} returned #{results.length} entries&quot;)
-      if block
-        results.each do |sr|
-          block.call(sr)
-        end
-      else
-        results
-      end
-    end
-    
     # Sets a tag, or list of tags, for this node.  Syntactic sugar for
     # @node[:tags].  
     #</diff>
      <filename>chef/lib/chef/recipe.rb</filename>
    </modified>
    <modified>
      <diff>@@ -69,10 +69,9 @@ class Chef
         @remote = &quot;origin&quot;
         @enable_submodules = false
         @shallow_clone = false
-        @force_deploy = false
         @scm_provider = Chef::Provider::Git
         @provider = Chef::Provider::Deploy::Timestamped
-        @allowed_actions.push(:deploy, :rollback)
+        @allowed_actions.push(:force_deploy, :deploy, :rollback)
       end
       
       # where the checked out/cloned code goes
@@ -244,15 +243,6 @@ class Chef
         )
       end
       
-      # Shall we run the deploy even if the code has not changed?
-      def force_deploy(arg=nil)
-        set_or_return(
-          :force_deploy,
-          arg,
-          :kind_of =&gt; [ TrueClass, FalseClass ]
-        )
-      end
-      
       def scm_provider(arg=nil)
         set_or_return(
           :scm_provider,
@@ -357,4 +347,4 @@ class Chef
       
     end
   end
-end
\ No newline at end of file
+end</diff>
      <filename>chef/lib/chef/resource/deploy.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,8 @@
 #
 # Author:: Adam Jacob (&lt;adam@opscode.com&gt;)
 # Author:: Thom May (&lt;thom@clearairturbulence.org&gt;)
-# Copyright:: Copyright (c) 2008 Opscode, Inc.
+# Author:: Nuo Yan (&lt;nuo@opscode.com&gt;)
+# Copyright:: Copyright (c) 2009 Opscode, Inc.
 # License:: Apache License, Version 2.0
 #
 # Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
@@ -24,6 +25,9 @@ require 'uri'
 require 'json'
 require 'tempfile'
 require 'singleton'
+require 'mixlib/authentication/signedheaderauth'
+
+include Mixlib::Authentication::SignedHeaderAuth
 
 class Chef
   class REST
@@ -32,47 +36,57 @@ class Chef
       include Singleton
     end
     
-    attr_accessor :url, :cookies
+    attr_accessor :url, :cookies, :signing_key
     
-    def initialize(url)
+    def initialize(url, client_name=Chef::Config[:node_name], signing_key=Chef::Config[:client_key])
       @url = url
       @cookies = CookieJar.instance
+      @client_name = client_name
+      if signing_key
+        @signing_key = load_signing_key(signing_key) 
+      else
+        @signing_key = nil
+      end
+    end
+
+    def load_signing_key(key)
+      if File.exists?(key) &amp;&amp; File.readable?(key)
+        IO.read(key)
+      else
+        raise Chef::Exceptions::PrivateKeyMissing, &quot;I cannot find #{key}, which you told me to use to sign requests!&quot;
+      end
     end
     
-    # Register for an OpenID
-    def register(user, pass, validation_token=nil)
-      Chef::Log.debug(&quot;Registering #{user} for an openid&quot;) 
-      registration = nil
+    # Register the client 
+    def register(name=Chef::Config[:node_name], destination=Chef::Config[:client_key])
+
+      if File.exists?(destination)
+        raise Chef::Exceptions::CannotWritePrivateKey, &quot;I cannot write your private key to #{destination} - check permissions?&quot; unless File.writable?(destination)
+      end
+
+      # First, try and create a new registration
       begin
-        registration = get_rest(&quot;registrations/#{user}&quot;)
-      rescue Net::HTTPServerException =&gt; e
-        unless e.message =~ /^404/
-          raise e
-        end
+        Chef::Log.info(&quot;Registering API Client #{name}&quot;)
+        response = post_rest(&quot;clients&quot;, {:name =&gt; name})
+      rescue Net::HTTPServerException 
+        # If that fails, go ahead and try and update it
+        response = put_rest(&quot;clients/#{name}&quot;, { :name =&gt; name, :private_key =&gt; true }) 
       end
-      unless registration
-        post_rest(
-          &quot;registrations&quot;, 
-          { 
-            :id =&gt; user, 
-            :password =&gt; pass, 
-            :validation_token =&gt; validation_token 
-          }
-        )
+
+      Chef::Log.debug(&quot;Registration response: #{response.inspect}&quot;)
+
+      raise Chef::Exceptions::CannotWritePrivateKey, &quot;The response from the server did not include a private key!&quot; unless response.has_key?(&quot;private_key&quot;)
+
+      begin
+        # Write out the private key
+        file = File.open(destination, &quot;w&quot;)
+        file.print(response[&quot;private_key&quot;])
+        file.close
+      rescue 
+        raise Chef::Exceptions::CannotWritePrivateKey, &quot;I cannot write your private key to #{destination}&quot;
       end
-    end
-    
-    # Authenticate 
-    def authenticate(user, pass)
-      Chef::Log.debug(&quot;Authenticating #{user} via openid&quot;) 
-      response = post_rest('openid/consumer/start', { 
-        &quot;openid_identifier&quot; =&gt; &quot;#{Chef::Config[:openid_url]}/openid/server/node/#{user}&quot;,
-        &quot;submit&quot; =&gt; &quot;Verify&quot;
-      })
-      post_rest(
-        &quot;#{Chef::Config[:openid_url]}#{response[&quot;action&quot;]}&quot;,
-        { &quot;password&quot; =&gt; pass }
-      )
+
+      true
     end
 
     # Send an HTTP GET request to the path
@@ -81,23 +95,23 @@ class Chef
     # path:: The path to GET
     # raw:: Whether you want the raw body returned, or JSON inflated.  Defaults 
     #   to JSON inflated.
-    def get_rest(path, raw=false)
-      run_request(:GET, create_url(path), false, 10, raw)    
+    def get_rest(path, raw=false, headers={})
+      run_request(:GET, create_url(path), headers, false, 10, raw)    
     end                               
                           
     # Send an HTTP DELETE request to the path
-    def delete_rest(path)             
-      run_request(:DELETE, create_url(path))       
+    def delete_rest(path, headers={}) 
+      run_request(:DELETE, create_url(path), headers)       
     end                               
     
     # Send an HTTP POST request to the path                                  
-    def post_rest(path, json)          
-      run_request(:POST, create_url(path), json)    
+    def post_rest(path, json, headers={})
+      run_request(:POST, create_url(path), headers, json)    
     end                               
                                       
     # Send an HTTP PUT request to the path
-    def put_rest(path, json)           
-      run_request(:PUT, create_url(path), json)
+    def put_rest(path, json, headers={})
+      run_request(:PUT, create_url(path), headers, json)
     end
     
     def create_url(path)
@@ -108,6 +122,18 @@ class Chef
       end
     end
     
+    def sign_request(http_method, private_key, user_id, body = &quot;&quot;, host=&quot;localhost&quot;)
+      #body = &quot;&quot; if body == false
+      timestamp = Time.now.utc.iso8601
+      sign_obj = Mixlib::Authentication::SignedHeaderAuth.signing_object(
+                                                         :http_method=&gt;http_method,
+                                                         :body=&gt;body,
+                                                         :user_id=&gt;user_id,
+                                                         :timestamp=&gt;timestamp)
+      signed =  sign_obj.sign(private_key).merge({:host =&gt; host})
+      signed.inject({}){|memo, kv| memo[&quot;#{kv[0].to_s.upcase}&quot;] = kv[1];memo}
+    end
+    
     # Actually run an HTTP request.  First argument is the HTTP method,
     # which should be one of :GET, :PUT, :POST or :DELETE.  Next is the
     # URL, then an object to include in the body (which will be converted with
@@ -117,7 +143,8 @@ class Chef
     # the helper methods (get_rest, post_rest, etc.)
     #
     # Will return the body of the response on success.
-    def run_request(method, url, data=false, limit=10, raw=false)
+    def run_request(method, url, headers={}, data=false, limit=10, raw=false)
+      
       http_retry_delay = Chef::Config[:http_retry_delay] 
       http_retry_count = Chef::Config[:http_retry_count]
 
@@ -129,21 +156,35 @@ class Chef
         if Chef::Config[:ssl_verify_mode] == :verify_none
           http.verify_mode = OpenSSL::SSL::VERIFY_NONE
         end
-        if File.exists?(Chef::Config[:ssl_client_cert])
+        if Chef::Config[:ssl_client_cert] &amp;&amp; File.exists?(Chef::Config[:ssl_client_cert])
           http.cert = OpenSSL::X509::Certificate.new(File.read(Chef::Config[:ssl_client_cert]))
           http.key = OpenSSL::PKey::RSA.new(File.read(Chef::Config[:ssl_client_key]))
         end
       end
+
       http.read_timeout = Chef::Config[:rest_timeout]
-      headers = Hash.new
+
       unless raw
-        headers = { 
+        headers = headers.merge({ 
           'Accept' =&gt; &quot;application/json&quot;,
-        }
+        })
       end
+      
       if @cookies.has_key?(&quot;#{url.host}:#{url.port}&quot;)
         headers['Cookie'] = @cookies[&quot;#{url.host}:#{url.port}&quot;]
       end
+
+      json_body = data ? data.to_json : nil 
+
+      if @signing_key
+        Chef::Log.debug(&quot;Signing the request as #{@client_name}&quot;)
+        if json_body
+          headers.merge!(sign_request(method, OpenSSL::PKey::RSA.new(@signing_key), @client_name, json_body, &quot;#{url.host}:#{url.port}&quot;))
+        else
+          headers.merge!(sign_request(method, OpenSSL::PKey::RSA.new(@signing_key), @client_name, &quot;&quot;, &quot;#{url.host}:#{url.port}&quot;))
+        end
+      end
+     
       req = nil
       case method
       when :GET
@@ -152,12 +193,16 @@ class Chef
         req = Net::HTTP::Get.new(req_path, headers)
       when :POST
         headers[&quot;Content-Type&quot;] = 'application/json' if data
-        req = Net::HTTP::Post.new(url.path, headers)          
-        req.body = data.to_json if data
+        req_path = &quot;#{url.path}&quot;
+        req_path &lt;&lt; &quot;?#{url.query}&quot; if url.query
+        req = Net::HTTP::Post.new(req_path, headers)          
+        req.body = json_body if json_body 
       when :PUT
         headers[&quot;Content-Type&quot;] = 'application/json' if data
-        req = Net::HTTP::Put.new(url.path, headers)
-        req.body = data.to_json if data
+        req_path = &quot;#{url.path}&quot;
+        req_path &lt;&lt; &quot;?#{url.query}&quot; if url.query
+        req = Net::HTTP::Put.new(req_path, headers)
+        req.body = json_body if json_body 
       when :DELETE
         req_path = &quot;#{url.path}&quot;
         req_path &lt;&lt; &quot;?#{url.query}&quot; if url.query
@@ -165,11 +210,12 @@ class Chef
       else
         raise ArgumentError, &quot;You must provide :GET, :PUT, :POST or :DELETE as the method&quot;
       end
+
+      Chef::Log.debug(&quot;Sending HTTP Request via #{req.method} to #{url.host}:#{url.port}/#{req.path}&quot;)
       
       # Optionally handle HTTP Basic Authentication
       req.basic_auth(url.user, url.password) if url.user
 
-      Chef::Log.debug(&quot;Sending HTTP Request via #{req.method} to #{req.path}&quot;)
       res = nil
       tf = nil
       http_retries = 1
@@ -199,7 +245,8 @@ class Chef
           end
           response
         end
-      rescue Errno::ECONNREFUSED
+
+      rescue Errno::ECONNREFUSED =&gt; e
         Chef::Log.error(&quot;Connection refused connecting to #{url.host}:#{url.port} for #{req.path} #{http_retries}/#{http_retry_count}&quot;)
         sleep(http_retry_delay)
         retry if (http_retries += 1) &lt; http_retry_count
@@ -216,7 +263,8 @@ class Chef
           @cookies[&quot;#{url.host}:#{url.port}&quot;] = res['set-cookie']
         end
         if res['content-type'] =~ /json/
-          JSON.parse(res.body)
+          response_body = res.body.chomp
+          JSON.parse(response_body)
         else
           if raw
             tf
@@ -228,11 +276,11 @@ class Chef
         if res['set-cookie']
           @cookies[&quot;#{url.host}:#{url.port}&quot;] = res['set-cookie']
         end
-        run_request(:GET, create_url(res['location']), false, limit - 1, raw)
+        run_request(:GET, create_url(res['location']), {}, false, limit - 1, raw)
       else
         res.error!
       end
     end
- 
+    
   end
 end</diff>
      <filename>chef/lib/chef/rest.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,6 @@
 #
 # Author:: Adam Jacob (&lt;adam@opscode.com&gt;)
+# Author:: Nuo Yan (&lt;nuo@opscode.com&gt;)
 # Copyright:: Copyright (c) 2008 Opscode, Inc.
 # License:: Apache License, Version 2.0
 #
@@ -30,7 +31,7 @@ class Chef
     include Chef::Mixin::ParamsValidate
     
     DESIGN_DOCUMENT = {
-      &quot;version&quot; =&gt; 3,
+      &quot;version&quot; =&gt; 6,
       &quot;language&quot; =&gt; &quot;javascript&quot;,
       &quot;views&quot; =&gt; {
         &quot;all&quot; =&gt; {
@@ -50,21 +51,22 @@ class Chef
             }
           }
           EOJS
-        },
-      },
+        }
+      }
     }
 
-    attr_accessor :couchdb_rev
+    attr_accessor :couchdb_rev, :couchdb_id
     
     # Create a new Chef::Role object.
-    def initialize()
+    def initialize
       @name = '' 
       @description = '' 
       @default_attributes = Mash.new
       @override_attributes = Mash.new
       @recipes = Array.new 
       @couchdb_rev = nil
-      @couchdb = Chef::CouchDB.new
+      @couchdb_id = nil
+      @couchdb = Chef::CouchDB.new 
     end
 
     def name(arg=nil) 
@@ -139,27 +141,50 @@ class Chef
       role.override_attributes(o[&quot;override_attributes&quot;])
       role.recipes(o[&quot;recipes&quot;])
       role.couchdb_rev = o[&quot;_rev&quot;] if o.has_key?(&quot;_rev&quot;)
+      role.couchdb_id = o[&quot;_id&quot;] if o.has_key?(&quot;_id&quot;)
       role 
     end
     
     # List all the Chef::Role objects in the CouchDB.  If inflate is set to true, you will get
     # the full list of all Roles, fully inflated.
-    def self.list(inflate=false)
-      rs = Chef::CouchDB.new.list(&quot;roles&quot;, inflate)
+    def self.cdb_list(inflate=false)
+      couchdb = Chef::CouchDB.new
+      rs = couchdb.list(&quot;roles&quot;, inflate)
       if inflate
         rs[&quot;rows&quot;].collect { |r| r[&quot;value&quot;] }
       else
         rs[&quot;rows&quot;].collect { |r| r[&quot;key&quot;] }
       end
     end
+
+    # Get the list of all roles from the API.
+    def self.list(inflate=false)
+      r = Chef::REST.new(Chef::Config[:chef_server_url])
+      if inflate
+        response = Hash.new
+        Chef::Search::Query.new.search(:role) do |n|
+          response[n.name] = n
+        end
+        response
+      else
+        r.get_rest(&quot;roles&quot;)
+      end
+    end
     
     # Load a role by name from CouchDB
+    def self.cdb_load(name)
+      couchdb = Chef::CouchDB.new
+      couchdb.load(&quot;role&quot;, name)
+    end
+    
+    # Load a role by name from the API
     def self.load(name)
-      Chef::CouchDB.new.load(&quot;role&quot;, name)
+      r = Chef::REST.new(Chef::Config[:chef_server_url])
+      r.get_rest(&quot;roles/#{name}&quot;)
     end
     
     # Remove this role from the CouchDB
-    def destroy
+    def cdb_destroy
       @couchdb.delete(&quot;role&quot;, @name, @couchdb_rev)
 
       if Chef::Config[:couchdb_version] == 0.9
@@ -167,26 +192,62 @@ class Chef
         rs[&quot;rows&quot;].each do |row| 
           node = row[&quot;doc&quot;]
           node.run_list.remove(&quot;role[#{@name}]&quot;)
-          node.save
+          node.cdb_save
         end
       else
-       Chef::Node.list.each do |node|
-         n = Chef::Node.load(node)
+       Chef::Node.cdb_list.each do |node|
+         n = Chef::Node.cdb_load(node)
          n.run_list.remove(&quot;role[#{@name}]&quot;)
-         n.save
+         n.cdb_save
        end
       end
     end
     
+    # Remove this role via the REST API
+    def destroy
+      r = Chef::REST.new(Chef::Config[:chef_server_url])
+      r.delete_rest(&quot;roles/#{@name}&quot;)
+      
+      Chef::Node.list.each do |node|
+        n = Chef::Node.load(node[0])
+        n.run_list.remove(&quot;role[#{@name}]&quot;)
+        n.save
+      end
+      
+    end
+    
     # Save this role to the CouchDB
-    def save
+    def cdb_save
       results = @couchdb.store(&quot;role&quot;, @name, self)
       @couchdb_rev = results[&quot;rev&quot;]
     end
     
+    # Save this role via the REST API
+    def save
+      r = Chef::REST.new(Chef::Config[:chef_server_url])
+      begin
+        r.put_rest(&quot;roles/#{@name}&quot;, self)
+      rescue Net::HTTPServerException =&gt; e
+        if e.response.code == &quot;404&quot;
+          r.post_rest(&quot;roles&quot;, self)
+        else
+          raise e
+        end
+      end
+      self
+    end
+    
+    # Create the role via the REST API
+    def create
+      r = Chef::REST.new(Chef::Config[:chef_server_url])
+      r.post_rest(&quot;roles&quot;, self)
+      self
+    end 
+    
     # Set up our CouchDB design document
     def self.create_design_document
-      Chef::CouchDB.new.create_design_document(&quot;roles&quot;, DESIGN_DOCUMENT)
+      couchdb = Chef::CouchDB.new
+      couchdb.create_design_document(&quot;roles&quot;, DESIGN_DOCUMENT)
     end
     
     # As a string
@@ -217,13 +278,13 @@ class Chef
         Chef::Log.warn(&quot;Loading #{short_name}&quot;)
         r = Chef::Role.from_disk(short_name, &quot;json&quot;)
         begin
-          couch_role = Chef::Role.load(short_name)
+          couch_role = Chef::Role.cdb_load(short_name)
           r.couchdb_rev = couch_role.couchdb_rev
           Chef::Log.debug(&quot;Replacing role #{short_name} with data from #{role_file}&quot;)
-        rescue Net::HTTPServerException
+        rescue Chef::Exceptions::CouchDBNotFound 
           Chef::Log.debug(&quot;Creating role #{short_name} with data from #{role_file}&quot;)
         end
-        r.save
+        r.cdb_save
       end
     end
 </diff>
      <filename>chef/lib/chef/role.rb</filename>
    </modified>
    <modified>
      <diff>@@ -112,6 +112,7 @@ class Chef
     end
 
     def expand(from='server')
+      couchdb = Chef::CouchDB.new
       recipes = Array.new
       default_attrs = Mash.new
       override_attrs = Mash.new
@@ -132,7 +133,7 @@ class Chef
             role = r.get_rest(&quot;roles/#{name}&quot;)
           elsif from == 'couchdb'
             # Load the role from couchdb
-            role = Chef::Role.load(name)
+            role = Chef::Role.cdb_load(name)
           end
           role.recipes.each { |r| recipes &lt;&lt;  r unless recipes.include?(r) }
           default_attrs = Chef::Mixin::DeepMerge.merge(default_attrs, role.default_attributes)</diff>
      <filename>chef/lib/chef/run_list.rb</filename>
    </modified>
    <modified>
      <diff>@@ -111,7 +111,7 @@ class Chef
             run_action(resource, ra)
           end
         rescue =&gt; e
-          Chef::Log.error(&quot;#{resource} (#{resource.source_line}) had an error:\n#{e}\n#{e.backtrace}&quot;)
+          Chef::Log.error(&quot;#{resource} (#{resource.source_line}) had an error:\n#{e}\n#{e.backtrace.join(&quot;\n&quot;)}&quot;)
           raise e unless resource.ignore_failure
         end
       end</diff>
      <filename>chef/lib/chef/runner.rb</filename>
    </modified>
    <modified>
      <diff>@@ -185,6 +185,8 @@ def create_cookbook(dir)
   sh &quot;mkdir -p #{File.join(dir, ENV[&quot;COOKBOOK&quot;], &quot;recipes&quot;)}&quot; 
   sh &quot;mkdir -p #{File.join(dir, ENV[&quot;COOKBOOK&quot;], &quot;definitions&quot;)}&quot; 
   sh &quot;mkdir -p #{File.join(dir, ENV[&quot;COOKBOOK&quot;], &quot;libraries&quot;)}&quot; 
+  sh &quot;mkdir -p #{File.join(dir, ENV[&quot;COOKBOOK&quot;], &quot;resources&quot;)}&quot; 
+  sh &quot;mkdir -p #{File.join(dir, ENV[&quot;COOKBOOK&quot;], &quot;providers&quot;)}&quot; 
   sh &quot;mkdir -p #{File.join(dir, ENV[&quot;COOKBOOK&quot;], &quot;files&quot;, &quot;default&quot;)}&quot; 
   sh &quot;mkdir -p #{File.join(dir, ENV[&quot;COOKBOOK&quot;], &quot;templates&quot;, &quot;default&quot;)}&quot; 
   unless File.exists?(File.join(dir, ENV[&quot;COOKBOOK&quot;], &quot;recipes&quot;, &quot;default.rb&quot;))
@@ -343,3 +345,63 @@ task :roles do
   end
 end
 
+desc &quot;Upload all cookbooks&quot;
+task :upload_cookbooks =&gt; [ :metadata ]
+task :upload_cookbooks do
+  Chef::Config[:cookbook_path] = [ File.join(TOPDIR, 'cookbooks'), File.join(TOPDIR, 'site-cookbooks') ]
+  cl = Chef::CookbookLoader.new
+  cl.each do |cookbook|
+    cook_meta = Chef::Cookbook::Metadata.new(cookbook)
+    upload_single_cookbook(cookbook.name.to_s, cook_meta.version)
+    puts &quot;* Uploaded #{cookbook.name.to_s}&quot;
+  end
+end
+
+desc &quot;Upload a single cookbook&quot;
+task :upload_cookbook =&gt; [ :metadata ]
+task :upload_cookbook, :cookbook do |t, args|
+  upload_single_cookbook(args.cookbook)
+  puts &quot;* Uploaded #{args.cookbook}&quot;
+end
+
+def upload_single_cookbook(cookbook_name, version=nil)
+  require 'chef/streaming_cookbook_uploader'
+  Chef::Log.level(:error)
+  Mixlib::Authentication::Log.logger = Chef::Log.logger
+  raise ArgumentError, &quot;OPSCODE_KEY must be set to your API Key&quot; unless ENV.has_key?(&quot;OPSCODE_KEY&quot;)
+  raise ArgumentError, &quot;OPSCODE_USER must be set to your Username&quot; unless ENV.has_key?(&quot;OPSCODE_USER&quot;)
+
+  Chef::Config.from_file(&quot;/etc/chef/client.rb&quot;)
+
+  tarball_name = &quot;#{cookbook_name}.tar.gz&quot;
+  temp_dir = File.join(Dir.tmpdir, &quot;chef-upload-cookbooks&quot;)
+  temp_cookbook_dir = File.join(temp_dir, cookbook_name)
+  FileUtils.mkdir(temp_dir) 
+  FileUtils.mkdir(temp_cookbook_dir)
+ 
+  child_folders = [ &quot;cookbooks/#{cookbook_name}&quot;, &quot;site-cookbooks/#{cookbook_name}&quot; ]
+  child_folders.each do |folder|
+    file_path = File.join(TOPDIR, folder, &quot;.&quot;)
+    FileUtils.cp_r(file_path, temp_cookbook_dir) if File.directory?(file_path)
+  end 
+      
+  system(&quot;tar&quot;, &quot;-C&quot;, temp_dir, &quot;-czf&quot;, File.join(temp_dir, tarball_name), &quot;./#{cookbook_name}&quot;)
+
+  r = Chef::REST.new(Chef::Config[:chef_server_url], ENV['OPSCODE_USER'], ENV['OPSCODE_KEY'])
+  begin
+    cb = r.get_rest(&quot;cookbooks/#{cookbook_name}&quot;)
+    cookbook_uploaded = true
+  rescue Net::HTTPServerException
+    cookbook_uploaded = false
+  end
+  puts &quot;* Uploading #{cookbook_name} (#{cookbook_uploaded ? 'new version' : 'first time'})&quot;
+  if cookbook_uploaded
+    Chef::StreamingCookbookUploader.put(&quot;#{Chef::Config[:chef_server_url]}/cookbooks/#{cookbook_name}/_content&quot;, ENV[&quot;OPSCODE_USER&quot;], ENV[&quot;OPSCODE_KEY&quot;], {:file =&gt; File.new(File.join(temp_dir, tarball_name)), :name =&gt; cookbook_name})
+  else
+    Chef::StreamingCookbookUploader.post(&quot;#{Chef::Config[:chef_server_url]}/cookbooks&quot;, ENV[&quot;OPSCODE_USER&quot;], ENV[&quot;OPSCODE_KEY&quot;], {:file =&gt; File.new(File.join(temp_dir, tarball_name)), :name =&gt; cookbook_name})
+  end
+
+  #delete temp files (e.g. /tmp/cookbooks and /tmp/cookbooks.tgz)
+  FileUtils.rm_rf temp_dir
+end
+</diff>
      <filename>chef/lib/chef/tasks/chef_repo.rake</filename>
    </modified>
    <modified>
      <diff>@@ -30,18 +30,9 @@ describe Chef::Client, &quot;run&quot; do
     to_stub = [
       :build_node,
       :register,
-      :authenticate,
-      :sync_library_files,
-      :sync_provider_files,
-      :sync_resource_files,
-      :sync_attribute_files,
-      :sync_definitions,
-      :sync_recipes,
+      :sync_cookbooks,
       :save_node,
-      :save_node,
-      :run_ohai,
-      :safe_name,
-      :node_name
+      :converge
     ]
     to_stub.each do |method|
       @client.stub!(method).and_return(true)
@@ -63,43 +54,13 @@ describe Chef::Client, &quot;run&quot; do
     @client.run
   end
   
-  it &quot;should register for an openid&quot; do
+  it &quot;should register for a client&quot; do
     @client.should_receive(:register).and_return(true)
     @client.run
   end
   
-  it &quot;should authenticate with the server&quot; do
-    @client.should_receive(:authenticate).and_return(true)
-    @client.run
-  end
-  
-  it &quot;should synchronize definitions from the server&quot; do
-    @client.should_receive(:sync_definitions).and_return(true)
-    @client.run
-  end
-  
-  it &quot;should synchronize recipes from the server&quot; do
-    @client.should_receive(:sync_recipes).and_return(true)
-    @client.run
-  end
-  
-  it &quot;should synchronize and load library files from the server&quot; do
-    @client.should_receive(:sync_library_files).and_return(true)
-    @client.run
-  end
-  
-  it &quot;should synchronize and load attribute files from the server&quot; do
-    @client.should_receive(:sync_attribute_files).and_return(true)
-    @client.run
-  end
-  
-  it &quot;should synchronize providers from the server&quot; do
-    @client.should_receive(:sync_provider_files).and_return(true)
-    @client.run
-  end
-  
-  it &quot;should synchronize resources from the server&quot; do
-    @client.should_receive(:sync_resource_files).and_return(true)
+  it &quot;should synchronize the cookbooks from the server&quot; do
+    @client.should_receive(:sync_cookbooks).and_return(true)
     @client.run
   end
   
@@ -113,11 +74,6 @@ describe Chef::Client, &quot;run&quot; do
     @client.run
   end
 
-  it &quot;should set the cookbook_path&quot; do
-    Chef::Config.should_receive('[]').with(:file_cache_path).
-      and_return('/var/chef/cache/cookbooks')
-    @client.run
-  end
 end
 
 describe Chef::Client, &quot;run_solo&quot; do
@@ -166,6 +122,7 @@ describe Chef::Client, &quot;build_node&quot; do
     Chef::REST.stub!(:new).and_return(@mock_rest)
     @client = Chef::Client.new
     Chef::Platform.stub!(:find_platform_and_version).and_return([&quot;FooOS&quot;, &quot;1.3.3.7&quot;])
+    Chef::Config[:node_name] = nil
   end
   
   it &quot;should set the name equal to the FQDN&quot; do
@@ -225,35 +182,34 @@ describe Chef::Client, &quot;register&quot; do
   before do
     @mock_rest = mock(&quot;Chef::REST&quot;, :null_object =&gt; true)
     @mock_rest.stub!(:get_rest).and_return(true)
+    @mock_rest.stub!(:register).and_return(true)
     Chef::REST.stub!(:new).and_return(@mock_rest)
     @chef_client = Chef::Client.new
     @chef_client.safe_name = &quot;testnode&quot;
+    @chef_client.node_name = &quot;testnode&quot;
     @chef_client.stub!(:determine_node_name).and_return(true)
-    @chef_client.stub!(:create_registration).and_return(true)
-    Chef::Application.stub!(:fatal!).and_return(true)
-    Chef::FileCache.stub!(:create_cache_path).and_return(&quot;/tmp&quot;)
-    Chef::FileCache.stub!(:load).and_return(&quot;/tmp/testnode&quot;)
-  end
-
-  it &quot;should log an appropriate debug message regarding registering an openid&quot; do
-    Chef::Log.should_receive(:debug).with(&quot;Registering testnode for an openid&quot;).and_return(true)
-    @chef_client.register
+    File.stub!(:exists?).and_return(false)
   end
+  
+  describe &quot;when the validation key is present&quot; do
+    before(:each) do
+      File.stub!(:exists?).with(Chef::Config[:validation_key]).and_return(true)
+    end
 
-  it &quot;should fetch the registration based on safe_name from the chef server&quot; do
-    @mock_rest.should_receive(:get_rest).with(&quot;registrations/testnode&quot;).and_return(true)
-    @chef_client.register
-  end
+    it &quot;should sign requests with the validation key&quot; do
+      Chef::REST.should_receive(:new).with(Chef::Config[:client_url], Chef::Config[:validation_client_name], Chef::Config[:validation_key]).and_return(@mock_rest)
+      @chef_client.register
+    end
 
-  it &quot;should load the secret from disk&quot; do
-    Chef::FileCache.should_receive(:load).with(File.join(&quot;registration&quot;, &quot;testnode&quot;)).and_return(&quot;/tmp/testnode&quot;)
-    @chef_client.register
+    it &quot;should register for a new key-pair&quot; do
+      @mock_rest.should_receive(:register).with(&quot;testnode&quot;, Chef::Config[:client_key])
+      @chef_client.register
+    end
   end
 
-  it &quot;should cause chef to die fatally if the filecache cannot find the registration&quot; do
-    Chef::FileCache.stub!(:load).with(File.join(&quot;registration&quot;, &quot;testnode&quot;)).and_raise(Chef::Exceptions::FileNotFound)
-    Chef::Application.should_receive(:fatal!).with(/^.*$/, 3).and_return(true) 
-    @chef_client.register
+  it &quot;should setup the rest client to use the client key-pair&quot; do
+    Chef::REST.should_receive(:new).with(Chef::Config[:chef_server_url]).and_return(@mock_rest)
+    @chef_client.register 
   end
 
 end
@@ -273,3 +229,4 @@ describe Chef::Client, &quot;run_ohai&quot; do
     @chef_client.run_ohai
   end
 end
+</diff>
      <filename>chef/spec/unit/client_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -18,236 +18,245 @@
 
 require File.expand_path(File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;spec_helper&quot;))
 
-describe Chef::CouchDB, &quot;new&quot; do
-  before do
+describe Chef::CouchDB do
+  before(:each) do
     @mock_rest = mock(&quot;Chef::REST&quot;, :null_object =&gt; true)
     @mock_rest.stub!(:run_request).and_return({&quot;couchdb&quot; =&gt; &quot;Welcome&quot;, &quot;version&quot; =&gt;&quot;0.9.0&quot;})
     @mock_rest.stub!(:url).and_return(&quot;http://localhost:5984&quot;)
     Chef::REST.stub!(:new).and_return(@mock_rest)
-  end
-  
-  it &quot;should create a new Chef::REST object from the default url&quot; do
-    Chef::Config[:couchdb_url] = &quot;http://monkey&quot;
-    Chef::REST.should_receive(:new).with(&quot;http://monkey&quot;)
-    Chef::CouchDB.new
+    @couchdb = Chef::CouchDB.new
+    Chef::Nanite.stub!(:push).and_return(true)
+    Chef::Nanite.stub!(:in_event).and_return(true)
+    Chef::Nanite.stub!(:start_mapper).and_return(true)
   end
 
-  it &quot;should create a new Chef::REST object from a provided url&quot; do
-    Chef::REST.should_receive(:new).with(&quot;http://monkeypants&quot;)
-    Chef::CouchDB.new(&quot;http://monkeypants&quot;)
-  end  
-end
+  describe &quot;new&quot; do
+    it &quot;should create a new Chef::REST object from the default url&quot; do
+      old_url = Chef::Config[:couchdb_url]
+      Chef::Config[:couchdb_url] = &quot;http://monkey&quot;
+      Chef::REST.should_receive(:new).with(&quot;http://monkey&quot;, nil, nil)
+      Chef::CouchDB.new
+      Chef::Config[:couchdb_url] = old_url
+    end
 
-describe Chef::CouchDB, &quot;create_db&quot; do
-  before(:each) do
-    @mock_rest = mock(&quot;Chef::REST&quot;, :null_object =&gt; true)
-    @mock_rest.stub!(:get_rest).and_return([ &quot;chef&quot; ])
-    @mock_rest.stub!(:put_rest).and_return(true)
-    Chef::REST.stub!(:new).and_return(@mock_rest)
-  end
-  
-  def do_create_db
-    couch = Chef::CouchDB.new
-    couch.create_db
-  end
-  
-  it &quot;should get a list of current databases&quot; do
-    @mock_rest.should_receive(:get_rest).and_return([&quot;chef&quot;])
-    do_create_db
-  end
-  
-  it &quot;should create the chef database if it does not exist&quot; do
-    @mock_rest.stub!(:get_rest).and_return([])
-    @mock_rest.should_receive(:put_rest).with(&quot;chef&quot;, {}).and_return(true)
-    do_create_db
+    it &quot;should create a new Chef::REST object from a provided url&quot; do
+      Chef::REST.should_receive(:new).with(&quot;http://monkeypants&quot;, nil, nil)
+      Chef::CouchDB.new(&quot;http://monkeypants&quot;)
+    end 
   end
-  
-  it &quot;should not create the chef database if it does exist&quot; do
-    @mock_rest.stub!(:get_rest).and_return([&quot;chef&quot;])
-    @mock_rest.should_not_receive(:put_rest)
-    do_create_db
-  end
-  
-  it &quot;should return 'chef'&quot; do
-    do_create_db.should eql(&quot;chef&quot;)
+
+  describe &quot;create_db&quot; do
+    before(:each) do
+      @couchdb.stub!(:create_design_document).and_return(true)
+    end
+    
+    it &quot;should get a list of current databases&quot; do
+      @mock_rest.should_receive(:get_rest).and_return([&quot;chef&quot;])
+      @couchdb.create_db
+    end
+    
+    it &quot;should create the chef database if it does not exist&quot; do
+      @mock_rest.stub!(:get_rest).and_return([])
+      @mock_rest.should_receive(:put_rest).with(&quot;chef&quot;, {}).and_return(true)
+      @couchdb.create_db
+    end
+    
+    it &quot;should not create the chef database if it does exist&quot; do
+      @mock_rest.stub!(:get_rest).and_return([&quot;chef&quot;])
+      @mock_rest.should_not_receive(:put_rest)
+      @couchdb.create_db
+    end
+    
+    it &quot;should return 'chef'&quot; do
+      @couchdb.create_db.should eql(&quot;chef&quot;)
+    end
   end
-end
 
-describe Chef::CouchDB, &quot;create_design_document&quot; do
-  before(:each) do
-    @mock_rest = mock(&quot;Chef::REST&quot;, :null_object =&gt; true)
-    @mock_design = {
-      &quot;version&quot; =&gt; 1,
-      &quot;_rev&quot; =&gt; 1
-    }
-    @mock_data = {
-      &quot;version&quot; =&gt; 1,
-      &quot;language&quot; =&gt; &quot;javascript&quot;,
-      &quot;views&quot; =&gt; {
-        &quot;all&quot; =&gt; {
-          &quot;map&quot; =&gt; &lt;&lt;-EOJS
-          function(doc) { 
-            if (doc.chef_type == &quot;node&quot;) {
-              emit(doc.name, doc);
+  describe &quot;create_design_document&quot; do
+    before(:each) do
+      @mock_design = {
+        &quot;version&quot; =&gt; 1,
+        &quot;_rev&quot; =&gt; 1
+      }
+      @mock_data = {
+        &quot;version&quot; =&gt; 1,
+        &quot;language&quot; =&gt; &quot;javascript&quot;,
+        &quot;views&quot; =&gt; {
+          &quot;all&quot; =&gt; {
+            &quot;map&quot; =&gt; &lt;&lt;-EOJS
+            function(doc) { 
+              if (doc.chef_type == &quot;node&quot;) {
+                emit(doc.name, doc);
+              }
             }
-          }
-          EOJS
-        },
+            EOJS
+          },
+        }
       }
-    }
-    @mock_rest.stub!(:get_rest).and_return(@mock_design)
-    @mock_rest.stub!(:put_rest).and_return(true)
-    Chef::REST.stub!(:new).and_return(@mock_rest)
-    @couchdb = Chef::CouchDB.new
-    @couchdb.stub!(:create_db).and_return(true)
-  end
-  
-  def do_create_design_document
-    @couchdb.create_design_document(&quot;bob&quot;, @mock_data)
-  end
-  
-  it &quot;should create the database if it does not exist&quot; do
-    @couchdb.should_receive(:create_db).and_return(true)
-    do_create_design_document
-  end
-  
-  it &quot;should fetch the existing design document&quot; do
-    @mock_rest.should_receive(:get_rest).with(&quot;chef/_design%2Fbob&quot;)
-    do_create_design_document
-  end
-  
-  it &quot;should populate the _rev in the new design if the versions dont match&quot; do
-    @mock_data[&quot;version&quot;] = 2
-    do_create_design_document
-    @mock_data[&quot;_rev&quot;].should eql(1)
-  end
-  
-  it &quot;should create the view if it requires updating&quot; do
-    @mock_data[&quot;version&quot;] = 2
-    @mock_rest.should_receive(:put_rest).with(&quot;chef/_design%2Fbob&quot;, @mock_data)
-    do_create_design_document
-  end
-  
-  it &quot;should not create the view if it does not require updating&quot; do
-    @mock_data[&quot;version&quot;] = 1
-    @mock_rest.should_not_receive(:put_rest)
-    do_create_design_document
+      @mock_rest.stub!(:get_rest).and_return(@mock_design)
+      @mock_rest.stub!(:put_rest).and_return(true)
+      @couchdb.stub!(:create_db).and_return(true)
+    end
+    
+    def do_create_design_document
+      @couchdb.create_design_document(&quot;bob&quot;, @mock_data)
+    end
+    
+    it &quot;should create the database if it does not exist&quot; do
+      @couchdb.should_receive(:create_db).and_return(true)
+      do_create_design_document
+    end
+    
+    it &quot;should fetch the existing design document&quot; do
+      @mock_rest.should_receive(:get_rest).with(&quot;chef/_design/bob&quot;)
+      do_create_design_document
+    end
+    
+    it &quot;should populate the _rev in the new design if the versions dont match&quot; do
+      @mock_data[&quot;version&quot;] = 2
+      do_create_design_document
+      @mock_data[&quot;_rev&quot;].should eql(1)
+    end
+    
+    it &quot;should create the view if it requires updating&quot; do
+      @mock_data[&quot;version&quot;] = 2
+      @mock_rest.should_receive(:put_rest).with(&quot;chef/_design%2Fbob&quot;, @mock_data)
+      do_create_design_document
+    end
+    
+    it &quot;should not create the view if it does not require updating&quot; do
+      @mock_data[&quot;version&quot;] = 1
+      @mock_rest.should_not_receive(:put_rest)
+      do_create_design_document
+    end
   end
-end
 
-describe Chef::CouchDB, &quot;store&quot; do
-  it &quot;should put the object into couchdb&quot; do
-    @mock_rest = mock(&quot;Chef::REST&quot;, :null_object =&gt; true)
-    @mock_rest.should_receive(:put_rest).with(&quot;chef/node_bob&quot;, {}).and_return(true)
-    Chef::REST.stub!(:new).and_return(@mock_rest)
-    Chef::CouchDB.new.store(&quot;node&quot;, &quot;bob&quot;, {})
-  end
-end
+  describe &quot;store&quot; do
+    before(:each) do 
+      @mock_results = {
+        &quot;rows&quot; =&gt; [
+          &quot;id&quot; =&gt; 'a0934635-e111-45d9-8223-cb58e1c9434c'
+        ]
+      }
+      @couchdb.stub!(:get_view).with(&quot;id_map&quot;, &quot;name_to_id&quot;, :key =&gt; [ &quot;node&quot;, &quot;bob&quot; ]).and_return(@mock_results)
+    end
 
-describe Chef::CouchDB, &quot;load&quot; do
-  it &quot;should load the object from couchdb&quot; do
-    @mock_rest = mock(&quot;Chef::REST&quot;, :null_object =&gt; true)
-    @mock_rest.should_receive(:get_rest).with(&quot;chef/node_bob&quot;).and_return(true)
-    Chef::REST.stub!(:new).and_return(@mock_rest)
-    Chef::CouchDB.new.load(&quot;node&quot;, &quot;bob&quot;).should eql(true)
-  end
-end
+    it &quot;should put the object into couchdb with a pre-existing GUID&quot; do
+      @mock_rest.should_receive(:put_rest).with(&quot;chef/#{@mock_results[&quot;rows&quot;][0][&quot;id&quot;]}&quot;, {}).and_return(true)
+      @couchdb.store(&quot;node&quot;, &quot;bob&quot;, {})
+    end
 
-describe Chef::CouchDB, &quot;delete&quot; do
-  before(:each) do
-    @mock_current = {
-      &quot;version&quot; =&gt; 1,
-      &quot;_rev&quot; =&gt; 1
-    }
-    @mock_rest = mock(&quot;Chef::REST&quot;, :null_object =&gt; true)
-    @mock_rest.stub!(:get_rest).and_return(@mock_current)
-    @mock_rest.stub!(:delete_rest).and_return(true)
-    Chef::REST.stub!(:new).and_return(@mock_rest)
-  end
-  
-  def do_delete(rev=nil)
-    Chef::REST.stub!(:new).and_return(@mock_rest)
-    Chef::CouchDB.new.delete(&quot;node&quot;, &quot;bob&quot;, rev)
-  end
-  
-  it &quot;should remove the object from couchdb with a specific revision&quot; do
-    @mock_rest.should_receive(:delete_rest).with(&quot;chef/node_bob?rev=1&quot;)
-    do_delete(1)  
-  end
-  
-  it &quot;should remove the object from couchdb based on the couchdb_rev of the current obj&quot; do
-    mock_real = mock(&quot;Inflated Object&quot;)
-    mock_real.stub!(:respond_to?).and_return(true)
-    mock_real.stub!(:couchdb_rev).and_return(2)
-    @mock_rest.should_receive(:get_rest).with(&quot;chef/node_bob&quot;).and_return(mock_real)
-    @mock_rest.should_receive(:delete_rest).with(&quot;chef/node_bob?rev=2&quot;)
-    do_delete
-  end
-  
-  it &quot;should remove the object from couchdb based on the current objects rev&quot; do
-    @mock_rest.should_receive(:delete_rest).with(&quot;chef/node_bob?rev=1&quot;)
-    do_delete
+    it &quot;should put the object into couchdb with a new GUID&quot; do
+      @mock_results = { &quot;rows&quot; =&gt; [] }
+      @couchdb.stub!(:get_view).with(&quot;id_map&quot;, &quot;name_to_id&quot;, :key =&gt; [ &quot;node&quot;, &quot;bob&quot; ]).and_return(@mock_results)
+      UUIDTools::UUID.stub!(:random_create).and_return(&quot;aaaaaaaa-xxxx-xxxx-xxxx-xxxxxxxxxxx&quot;)
+      @mock_rest.should_receive(:put_rest).with(&quot;chef/aaaaaaaa-xxxx-xxxx-xxxx-xxxxxxxxxxx&quot;, {}).and_return(true)
+      @couchdb.store(&quot;node&quot;, &quot;bob&quot;, {})
+    end
+
+    it &quot;should send the object to nanite for indexing&quot; do
+      Chef::Nanite.should_receive(:push)
+      @couchdb.store(&quot;node&quot;, &quot;bob&quot;, {})
+    end
   end
-end
 
-describe Chef::CouchDB, &quot;list&quot; do
-  before(:each) do
-    @mock_rest = mock(&quot;Chef::REST&quot;, :null_object =&gt; true, :url =&gt; &quot;http://monkeypants&quot;)
-    Chef::REST.stub!(:new).and_return(@mock_rest)
-    @couch = Chef::CouchDB.new(&quot;http://monkeypants&quot;)
-    Chef::Config.stub!(:[]).with(:couchdb_database).and_return(&quot;chef&quot;)
+  describe &quot;load&quot; do
+    before(:each) do 
+      @mock_node = Chef::Node.new()
+      @mock_node.name(&quot;bob&quot;)
+      @couchdb.stub!(:find_by_name).with(&quot;node&quot;, &quot;bob&quot;).and_return(@mock_node)
+    end
+
+    it &quot;should load the object from couchdb&quot; do
+      @couchdb.load(&quot;node&quot;, &quot;bob&quot;).should eql(@mock_node)
+    end
   end
-  
-  describe &quot;on couchdb 0.8&quot; do
-    before do
-      Chef::Config.stub!(:[]).with(:couchdb_version).and_return(0.8)
+
+  describe &quot;delete&quot; do
+    before(:each) do
+      @mock_current = {
+        &quot;version&quot; =&gt; 1,
+        &quot;_rev&quot; =&gt; 1
+      }
+      @mock_rest.stub!(:get_rest).and_return(@mock_current)
+      @mock_rest.stub!(:delete_rest).and_return(true)
+      @mock_node = Chef::Node.new()
+      @mock_node.name(&quot;bob&quot;)
+      @mock_node.couchdb_rev = 15
+      @couchdb.stub!(:find_by_name).with(&quot;node&quot;, &quot;bob&quot;, true).and_return([ @mock_node, &quot;ax&quot; ])
     end
     
-    it &quot;should get the view for all objects if inflate is true&quot; do
-      @mock_rest.should_receive(:get_rest).with(&quot;chef/_view/node/all&quot;).and_return(true)
-      @couch.list(&quot;node&quot;, true)
+    def do_delete(rev=nil)
+      @couchdb.delete(&quot;node&quot;, &quot;bob&quot;, rev)
     end
-
-    it &quot;should get the view for just the object id's if inflate is false&quot; do
-      @mock_rest.should_receive(:get_rest).with(&quot;chef/_view/node/all_id&quot;).and_return(true)
-      @couch.list(&quot;node&quot;, false)
+    
+    it &quot;should remove the object from couchdb with a specific revision&quot; do
+      @mock_rest.should_receive(:delete_rest).with(&quot;chef/ax?rev=1&quot;)
+      do_delete(1)  
+    end
+    
+    it &quot;should remove the object from couchdb based on the couchdb_rev of the current obj&quot; do
+      @mock_rest.should_receive(:delete_rest).with(&quot;chef/ax?rev=15&quot;)
+      do_delete
     end
   end
 
-  describe &quot;on couchdb 0.9&quot; do
-    before do
-      Chef::Config.stub!(:[]).with(:couchdb_version).and_return(0.9)
+  describe &quot;list&quot; do
+    before(:each) do
+      Chef::Config.stub!(:[]).with(:couchdb_database).and_return(&quot;chef&quot;)
+      @mock_response = mock(&quot;Chef::CouchDB::Response&quot;, :null_object =&gt; true)
     end
     
-    it &quot;should get the view for all objects if inflate is true&quot; do
-      @mock_rest.should_receive(:get_rest).with(&quot;chef/_design/node/_view/all&quot;).and_return(true)
-      @couch.list(&quot;node&quot;, true)
+    describe &quot;on couchdb 0.8&quot; do
+      before(:each) do
+        Chef::Config.stub!(:[]).with(:couchdb_version).and_return(0.8)
+      end
+      
+      it &quot;should get the view for all objects if inflate is true&quot; do
+        @mock_rest.should_receive(:get_rest).with(&quot;chef/_view/node/all&quot;).and_return(@mock_response)
+        @couchdb.list(&quot;node&quot;, true)
+      end
+
+      it &quot;should get the view for just the object id's if inflate is false&quot; do
+        @mock_rest.should_receive(:get_rest).with(&quot;chef/_view/node/all_id&quot;).and_return(@mock_response)
+        @couchdb.list(&quot;node&quot;, false)
+      end
     end
 
-    it &quot;should get the view for just the object id's if inflate is false&quot; do
-      @mock_rest.should_receive(:get_rest).with(&quot;chef/_design/node/_view/all_id&quot;).and_return(true)
-      @couch.list(&quot;node&quot;, false)
+    describe &quot;on couchdb 0.9&quot; do
+      before do
+        Chef::Config.stub!(:[]).with(:couchdb_version).and_return(0.9)
+      end
+      
+      it &quot;should get the view for all objects if inflate is true&quot; do
+        @mock_rest.should_receive(:get_rest).with(&quot;chef/_design/node/_view/all&quot;).and_return(@mock_response)
+        @couchdb.list(&quot;node&quot;, true)
+      end
+
+      it &quot;should get the view for just the object id's if inflate is false&quot; do
+        @mock_rest.should_receive(:get_rest).with(&quot;chef/_design/node/_view/all_id&quot;).and_return(@mock_response)
+        @couchdb.list(&quot;node&quot;, false)
+      end
     end
   end
-end
 
-describe Chef::CouchDB, &quot;has_key?&quot; do
-  before(:each) do
-    @mock_rest = mock(&quot;Chef::REST&quot;, :null_object =&gt; true)
-    Chef::REST.stub!(:new).and_return(@mock_rest)
-  end
-  
-  it &quot;should return true if the object exists&quot; do
-    @mock_rest.should_receive(:get_rest).and_return(true)
-    Chef::CouchDB.new.has_key?(&quot;node&quot;, &quot;bob&quot;).should eql(true)
-  end
-  
-  it &quot;should return false if the object does not exist&quot; do
-    @mock_rest.should_receive(:get_rest).and_raise(ArgumentError)
-    Chef::CouchDB.new.has_key?(&quot;node&quot;, &quot;bob&quot;).should eql(false)
+  describe &quot;has_key?&quot; do
+    it &quot;should return true if the object exists&quot; do
+      @couchdb.stub!(:find_by_name).with(&quot;node&quot;, &quot;bob&quot;).and_return(true)
+      @couchdb.has_key?(&quot;node&quot;, &quot;bob&quot;).should eql(true)
+    end
+    
+    it &quot;should return false if the object does not exist&quot; do
+      @couchdb.stub!(:find_by_name).and_raise(Chef::Exceptions::CouchDBNotFound)
+      @couchdb.has_key?(&quot;node&quot;, &quot;bob&quot;).should eql(false)
+    end
   end
+
 end
 
+
+
+
 describe Chef::CouchDB, &quot;get_view&quot; do
   before do
     @mock_rest = mock(&quot;Chef::REST&quot;, :null_object =&gt; true, :url =&gt; &quot;http://monkeypants&quot;)
@@ -287,7 +296,7 @@ describe Chef::CouchDB, &quot;view_uri&quot; do
       @mock_rest.should_receive(:run_request).with(
         :GET, 
         URI.parse(&quot;http://monkeypants/&quot;), 
-        false, 
+        {},
         10, 
         false
       ).and_return({ &quot;version&quot; =&gt; &quot;0.9&quot; })</diff>
      <filename>chef/spec/unit/couchdb_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -489,7 +489,7 @@ describe Chef::Node::Attribute do
         {
           &quot;one&quot; =&gt;  { &quot;two&quot; =&gt; &quot;three&quot; },
           &quot;hut&quot; =&gt;  { &quot;two&quot; =&gt; &quot;three&quot; },
-          &quot;place&quot; =&gt; { },
+          &quot;place&quot; =&gt; { }
         },
         {
           &quot;one&quot; =&gt;  { &quot;four&quot; =&gt; &quot;five&quot; },</diff>
      <filename>chef/spec/unit/node/attribute_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,6 +21,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;spec_helper&quot;))
 describe Chef::Node do
   before(:each) do
     Chef::Config.node_path(File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;data&quot;, &quot;nodes&quot;))
+    Nanite.stub!(:request).and_return(true)
     @node = Chef::Node.new()
   end
  
@@ -263,17 +264,6 @@ describe Chef::Node do
     end
   end
 
-  describe &quot;to_index&quot; do
-    before(:each) do
-      @node.foo(&quot;bar&quot;)
-    end
-    
-    it &quot;should return a hash with :index attributes&quot; do
-      @node.name(&quot;airplane&quot;)
-      @node.to_index.should == { &quot;foo&quot; =&gt; &quot;bar&quot;, &quot;index_name&quot; =&gt; &quot;node&quot;, &quot;id&quot; =&gt; &quot;node_airplane&quot;, &quot;name&quot; =&gt; &quot;airplane&quot; }
-    end
-  end
-
   describe &quot;to_s&quot; do
     it &quot;should turn into a string like node[name]&quot; do
       @node.name(&quot;airplane&quot;)
@@ -281,7 +271,71 @@ describe Chef::Node do
     end
   end
 
-  describe &quot;couchdb&quot; do
+  describe &quot;api model&quot; do
+    before(:each) do 
+      @rest = mock(&quot;Chef::REST&quot;)
+      Chef::REST.stub!(:new).and_return(@rest)
+      @query = mock(&quot;Chef::Search::Query&quot;)
+      Chef::Search::Query.stub!(:new).and_return(@query)
+    end
+
+    describe &quot;list&quot; do
+      describe &quot;inflated&quot; do
+        it &quot;should return a hash of node names and objects&quot; do
+          n1 = mock(&quot;Chef::Node&quot;, :name =&gt; &quot;one&quot;)
+          @query.should_receive(:search).with(:node).and_yield(n1)
+          r = Chef::Node.list(true)
+          r[&quot;one&quot;].should == n1
+        end
+      end
+
+      it &quot;should return a hash of node names and urls&quot; do
+        @rest.should_receive(:get_rest).and_return({ &quot;one&quot; =&gt; &quot;http://foo&quot; })
+        r = Chef::Node.list
+        r[&quot;one&quot;].should == &quot;http://foo&quot;
+      end
+    end
+
+    describe &quot;load&quot; do
+      it &quot;should load a node by name&quot; do
+        @rest.should_receive(:get_rest).with(&quot;nodes/monkey&quot;).and_return(&quot;foo&quot;)
+        Chef::Node.load(&quot;monkey&quot;).should == &quot;foo&quot;
+      end
+    end
+
+    describe &quot;destroy&quot; do
+      it &quot;should destroy a node&quot; do
+        @rest.should_receive(:delete_rest).with(&quot;nodes/monkey&quot;).and_return(&quot;foo&quot;)
+        @node.name(&quot;monkey&quot;)
+        @node.destroy
+      end
+    end
+
+    describe &quot;save&quot; do
+      it &quot;should update a node if it already exists&quot; do
+        @node.name(&quot;monkey&quot;)
+        @rest.should_receive(:put_rest).with(&quot;nodes/monkey&quot;, @node).and_return(&quot;foo&quot;)
+        @node.save
+      end
+
+      it &quot;should not try and create if it can update&quot; do
+        @node.name(&quot;monkey&quot;)
+        @rest.should_receive(:put_rest).with(&quot;nodes/monkey&quot;, @node).and_return(&quot;foo&quot;)
+        @rest.should_not_receive(:post_rest)
+        @node.save
+      end
+
+      it &quot;should create if it cannot update&quot; do
+        @node.name(&quot;monkey&quot;)
+        exception = mock(&quot;404 error&quot;, :code =&gt; &quot;404&quot;)
+        @rest.should_receive(:put_rest).and_raise(Net::HTTPServerException.new(&quot;foo&quot;, exception))
+        @rest.should_receive(:post_rest).with(&quot;nodes&quot;, @node)
+        @node.save
+      end
+    end
+  end
+
+  describe &quot;couchdb model&quot; do
     before(:each) do
       @mock_couch = mock(&quot;Chef::CouchDB&quot;)
     end
@@ -295,15 +349,15 @@ describe Chef::Node do
       end
 
       it &quot;should retrieve a list of nodes from CouchDB&quot; do
-        Chef::Node.list.should eql([&quot;avenue&quot;])
+        Chef::Node.cdb_list.should eql([&quot;avenue&quot;])
       end
 
       it &quot;should return just the ids if inflate is false&quot; do
-        Chef::Node.list(false).should eql([&quot;avenue&quot;])
+        Chef::Node.cdb_list(false).should eql([&quot;avenue&quot;])
       end
 
       it &quot;should return the full objects if inflate is true&quot; do
-        Chef::Node.list(true).should eql([&quot;a&quot;])
+        Chef::Node.cdb_list(true).should eql([&quot;a&quot;])
       end
     end
 
@@ -311,7 +365,7 @@ describe Chef::Node do
       it &quot;should load a node from couchdb by name&quot; do
         @mock_couch.should_receive(:load).with(&quot;node&quot;, &quot;coffee&quot;).and_return(true)
         Chef::CouchDB.stub!(:new).and_return(@mock_couch)
-        Chef::Node.load(&quot;coffee&quot;)
+        Chef::Node.cdb_load(&quot;coffee&quot;)
       end
     end
 
@@ -322,8 +376,7 @@ describe Chef::Node do
         node = Chef::Node.new
         node.name &quot;bob&quot;
         node.couchdb_rev = 1
-        Chef::Queue.should_receive(:send_msg).with(:queue, :remove, node)
-        node.destroy
+        node.cdb_destroy
       end
     end
 
@@ -331,20 +384,18 @@ describe Chef::Node do
       before(:each) do
         @mock_couch.stub!(:store).and_return({ &quot;rev&quot; =&gt; 33 })
         Chef::CouchDB.stub!(:new).and_return(@mock_couch)
-        Chef::Queue.stub!(:send_msg).and_return(true)
         @node = Chef::Node.new
         @node.name &quot;bob&quot;
         @node.couchdb_rev = 1
       end
 
       it &quot;should save the node to couchdb&quot; do
-        Chef::Queue.should_receive(:send_msg).with(:queue, :index, @node)
         @mock_couch.should_receive(:store).with(&quot;node&quot;, &quot;bob&quot;, @node).and_return({ &quot;rev&quot; =&gt; 33 })
-        @node.save
+        @node.cdb_save
       end
 
       it &quot;should store the new couchdb_rev&quot; do
-        @node.save
+        @node.cdb_save
         @node.couchdb_rev.should eql(33)
       end
     end</diff>
      <filename>chef/spec/unit/node_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -53,11 +53,16 @@ describe Chef::Provider::Deploy do
     @provider.should_receive(:cleanup!)
     @provider.deploy
   end
-  
-  it &quot;does not deploy when using the :deploy action if there is already a deploy at release_path&quot; do
+ 
+  it &quot;should not deploy if there is already a deploy at release_path, and it is the current release&quot; do
     @provider.stub!(:all_releases).and_return([@expected_release_dir])
-    @provider.should_not_receive(:enforce_ownership)
-    @provider.should_not_receive(:update_cached_repo)
+    @provider.should_not_receive(:deploy)
+    @provider.action_deploy
+  end
+
+  it &quot;should call action_rollback if there is already a deploy of this revision at release_path, and it is not the current release&quot; do
+    @provider.stub!(:all_releases).and_return([@expected_release_dir, &quot;102021&quot;])
+    @provider.should_receive(:action_rollback)
     @provider.action_deploy
   end
   
@@ -80,17 +85,59 @@ describe Chef::Provider::Deploy do
     @provider.action_force_deploy
   end
   
-  it &quot;sets the release path to the penultimate release, symlinks, and rm's the last release on rollback&quot; do
-    @provider.unstub!(:release_path)
-    all_releases = [&quot;/my/deploy/dir/releases/20040815162342&quot;, &quot;/my/deploy/dir/releases/20040700000000&quot;,
-                    &quot;/my/deploy/dir/releases/20040600000000&quot;, &quot;/my/deploy/dir/releases/20040500000000&quot;].sort!
-    Dir.stub!(:glob).with(&quot;/my/deploy/dir/releases/*&quot;).and_return(all_releases)
-    @provider.should_receive(:symlink)
-    FileUtils.should_receive(:rm_rf).with(&quot;/my/deploy/dir/releases/20040815162342&quot;)
-    @provider.action_rollback
-    @provider.release_path.should eql(&quot;/my/deploy/dir/releases/20040700000000&quot;)
+ 
+  describe &quot;on systems without broken Dir.glob results&quot; do
+    it &quot;sets the release path to the penultimate release when one is not specified, symlinks, and rm's the last release on rollback&quot; do
+      @provider.stub!(:release_path).and_return(&quot;/my/deploy/dir/releases/3&quot;)
+      all_releases = [&quot;/my/deploy/dir/releases/1&quot;, &quot;/my/deploy/dir/releases/2&quot;, &quot;/my/deploy/dir/releases/3&quot;, &quot;/my/deploy/dir/releases/4&quot;, &quot;/my/deploy/dir/releases/5&quot;]
+      Dir.stub!(:glob).with(&quot;/my/deploy/dir/releases/*&quot;).and_return(all_releases)
+      @provider.should_receive(:symlink)
+      FileUtils.should_receive(:rm_rf).with(&quot;/my/deploy/dir/releases/4&quot;)
+      FileUtils.should_receive(:rm_rf).with(&quot;/my/deploy/dir/releases/5&quot;)
+      @provider.action_rollback
+      @provider.release_path.should eql(&quot;/my/deploy/dir/releases/3&quot;)
+    end
+
+    it &quot;sets the release path to the specified release, symlinks, and rm's any newer releases on rollback&quot; do
+      @provider.unstub!(:release_path)
+      all_releases = [&quot;/my/deploy/dir/releases/20040815162342&quot;, &quot;/my/deploy/dir/releases/20040700000000&quot;,
+                      &quot;/my/deploy/dir/releases/20040600000000&quot;, &quot;/my/deploy/dir/releases/20040500000000&quot;].sort!
+      Dir.stub!(:glob).with(&quot;/my/deploy/dir/releases/*&quot;).and_return(all_releases)
+      @provider.should_receive(:symlink)
+      FileUtils.should_receive(:rm_rf).with(&quot;/my/deploy/dir/releases/20040815162342&quot;)
+      @provider.action_rollback
+      @provider.release_path.should eql(&quot;/my/deploy/dir/releases/20040700000000&quot;)
+    end
+
+    it &quot;sets the release path to the penultimate release, symlinks, and rm's the last release on rollback&quot; do
+      @provider.unstub!(:release_path)
+      all_releases = [ &quot;/my/deploy/dir/releases/20040815162342&quot;,
+                       &quot;/my/deploy/dir/releases/20040700000000&quot;,
+                       &quot;/my/deploy/dir/releases/20040600000000&quot;,
+                       &quot;/my/deploy/dir/releases/20040500000000&quot;]
+      Dir.stub!(:glob).with(&quot;/my/deploy/dir/releases/*&quot;).and_return(all_releases)
+      @provider.should_receive(:symlink)
+      FileUtils.should_receive(:rm_rf).with(&quot;/my/deploy/dir/releases/20040815162342&quot;)
+      @provider.action_rollback
+      @provider.release_path.should eql(&quot;/my/deploy/dir/releases/20040700000000&quot;)
+    end
   end
-  
+
+  describe &quot;CHEF-628: on systems with broken Dir.glob results&quot; do
+    it &quot;sets the release path to the penultimate release, symlinks, and rm's the last release on rollback&quot; do
+      @provider.unstub!(:release_path)
+      all_releases = [ &quot;/my/deploy/dir/releases/20040500000000&quot;,
+                       &quot;/my/deploy/dir/releases/20040600000000&quot;,
+                       &quot;/my/deploy/dir/releases/20040700000000&quot;,
+                       &quot;/my/deploy/dir/releases/20040815162342&quot; ]
+      Dir.stub!(:glob).with(&quot;/my/deploy/dir/releases/*&quot;).and_return(all_releases)
+      @provider.should_receive(:symlink)
+      FileUtils.should_receive(:rm_rf).with(&quot;/my/deploy/dir/releases/20040815162342&quot;)
+      @provider.action_rollback
+      @provider.release_path.should eql(&quot;/my/deploy/dir/releases/20040700000000&quot;)
+    end
+  end
+
   it &quot;raises a runtime error when there's no release to rollback to&quot; do
     all_releases = []
     Dir.stub!(:glob).with(&quot;/my/deploy/dir/releases/*&quot;).and_return(all_releases)</diff>
      <filename>chef/spec/unit/provider/deploy_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -129,7 +129,7 @@ describe Chef::Provider::Git do
                       &quot;b7d19519a1c15f1c1a324e2683bd728b6198ce5a\trefs/tags/0.7.8^{}\n&quot;+
                       &quot;ebc1b392fe7e8f0fbabc305c299b4d365d2b4d9b\trefs/tags/chef-server-package&quot;
       @resource.revision ''
-      @stdout.stub(:string).and_return(lots_of_shas)
+      @stdout.stub!(:string).and_return(lots_of_shas)
       @provider.should_receive(:popen4).and_yield(&quot;pid&quot;,&quot;stdin&quot;,@stdout,@stderr).and_return(@exitstatus)
       @provider.revision_sha.should eql(&quot;28af684d8460ba4793eda3e7ac238c864a5d029a&quot;)
     end
@@ -199,13 +199,15 @@ describe Chef::Provider::Git do
     @provider.should_receive(:clone)
     @provider.should_receive(:checkout)
     @provider.should_receive(:enable_submodules)
+    @resource.should_receive(:updated=).at_least(1).times.with(true)
     @provider.action_checkout
   end
-  
+
   it &quot;does a sync by running the sync command&quot; do
     ::File.stub!(:exist?).with(&quot;/my/deploy/dir&quot;).and_return(true)
     ::Dir.stub!(:entries).and_return(['.','..',&quot;lib&quot;, &quot;spec&quot;])
     @provider.should_receive(:sync)
+    @resource.should_receive(:updated=).at_least(1).times.with(true)
     @provider.action_sync
   end
   
@@ -213,6 +215,7 @@ describe Chef::Provider::Git do
     ::File.stub!(:exist?).with(&quot;/my/deploy/dir&quot;).and_return(false)
     @provider.should_receive(:action_checkout)
     @provider.should_not_receive(:run_command)
+    @resource.should_receive(:updated=).at_least(1).times.with(true)
     @provider.action_sync
   end
   
@@ -222,13 +225,15 @@ describe Chef::Provider::Git do
     @provider.stub!(:sync_command).and_return(&quot;huzzah!&quot;)
     @provider.should_receive(:action_checkout)
     @provider.should_not_receive(:run_command).with(:command =&gt; &quot;huzzah!&quot;, :cwd =&gt; &quot;/my/deploy/dir&quot;)
+    @resource.should_receive(:updated=).at_least(1).times.with(true)
     @provider.action_sync
   end
   
   it &quot;does an export by cloning the repo then removing the .git directory&quot; do
     @provider.should_receive(:action_checkout)
     FileUtils.should_receive(:rm_rf).with(@resource.destination + &quot;/.git&quot;)
+    @resource.should_receive(:updated=).at_least(1).times.with(true)
     @provider.action_export
   end
   
-end
\ No newline at end of file
+end</diff>
      <filename>chef/spec/unit/provider/git_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -145,6 +145,7 @@ end
 describe Chef::Provider::Group::Usermod, &quot;load_current_resource&quot; do
   before do
     @node = mock(&quot;Chef::Node&quot;, :null_object =&gt; true)
+    Chef::Node.stub!(:new).and_return(@node)
     @new_resource = mock(&quot;Chef::Resource::Group&quot;, :null_object =&gt; true, :group_name =&gt; &quot;aj&quot;)
     @provider = Chef::Provider::Group::Usermod.new(@node, @new_resource)
     File.stub!(:exists?).and_return(false)</diff>
      <filename>chef/spec/unit/provider/group/groupadd_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -47,8 +47,8 @@ describe Chef::Provider::HttpRequest, &quot;load_current_resource&quot; do
     @provider = Chef::Provider::HttpRequest.new(@node, @new_resource)
   end
   
-  it &quot;should set up a Chef::REST client&quot; do
-    Chef::REST.should_receive(:new).with(@new_resource.url)
+  it &quot;should set up a Chef::REST client, with no authentication&quot; do
+    Chef::REST.should_receive(:new).with(@new_resource.url, nil, nil)
     @provider.load_current_resource
   end
 end
@@ -83,7 +83,7 @@ describe Chef::Provider::HttpRequest, &quot;action_get&quot; do
   end
   
   it &quot;should run a GET request&quot; do
-    @rest.should_receive(:run_request).with(:GET, @rest.create_url, false, 10, false)
+    @rest.should_receive(:run_request).with(:GET, @rest.create_url, {}, false, 10, false)
     @provider.action_get
   end
   
@@ -117,13 +117,13 @@ describe Chef::Provider::HttpRequest, &quot;action_put&quot; do
   end
   
   it &quot;should run a PUT request with the message as the payload&quot; do
-    @rest.should_receive(:run_request).with(:PUT, @rest.create_url, @new_resource.message, 10, false)
+    @rest.should_receive(:run_request).with(:PUT, @rest.create_url, {}, @new_resource.message, 10, false)
     @provider.action_put
   end
   
   it &quot;should inflate a message block at runtime&quot; do
     @new_resource.stub!(:message).and_return(lambda { &quot;return&quot; })
-    @rest.should_receive(:run_request).with(:PUT, @rest.create_url, &quot;return&quot;, 10, false)    
+    @rest.should_receive(:run_request).with(:PUT, @rest.create_url, {}, &quot;return&quot;, 10, false)    
     @provider.action_put
   end
   
@@ -157,13 +157,13 @@ describe Chef::Provider::HttpRequest, &quot;action_post&quot; do
   end
   
   it &quot;should run a PUT request with the message as the payload&quot; do
-    @rest.should_receive(:run_request).with(:POST, @rest.create_url, @new_resource.message, 10, false)
+    @rest.should_receive(:run_request).with(:POST, @rest.create_url, {}, @new_resource.message, 10, false)
     @provider.action_post
   end
   
   it &quot;should inflate a message block at runtime&quot; do
     @new_resource.stub!(:message).and_return(lambda { &quot;return&quot; })
-    @rest.should_receive(:run_request).with(:POST, @rest.create_url, &quot;return&quot;, 10, false)    
+    @rest.should_receive(:run_request).with(:POST, @rest.create_url, {}, &quot;return&quot;, 10, false)    
     @provider.action_post
   end
   
@@ -197,7 +197,7 @@ describe Chef::Provider::HttpRequest, &quot;action_delete&quot; do
   end
   
   it &quot;should run a DELETE request&quot; do
-    @rest.should_receive(:run_request).with(:DELETE, @rest.create_url, false, 10, false)
+    @rest.should_receive(:run_request).with(:DELETE, @rest.create_url, {}, false, 10, false)
     @provider.action_delete
   end
   
@@ -205,4 +205,4 @@ describe Chef::Provider::HttpRequest, &quot;action_delete&quot; do
     @new_resource.should_receive(:updated=).with(true)
     @provider.action_delete
   end
-end
\ No newline at end of file
+end</diff>
      <filename>chef/spec/unit/provider/http_request_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -59,6 +59,12 @@ describe Chef::Provider::Package::Portage, &quot;load_current_resource&quot; do
     @current_resource.should_receive(:version).with(&quot;1.0.0&quot;)
     @provider.load_current_resource
   end
+
+  it &quot;should return a current resource with the correct version if the package is found with revision&quot; do
+    ::Dir.stub!(:entries).and_return(&quot;git-1.0.0-r1&quot;)
+    @current_resource.should_receive(:version).with(&quot;1.0.0-r1&quot;)
+    @provider.load_current_resource
+  end
   
   it &quot;should return a current resource with a nil version if the package is not found&quot; do
     ::Dir.stub!(:entries).and_return(&quot;notgit-1.0.0&quot;)</diff>
      <filename>chef/spec/unit/provider/package/portage_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -129,12 +129,6 @@ describe Chef::Provider::Service::Freebsd, &quot;load_current_resource&quot; do
       @provider.load_current_resource
     end
 
-    it &quot;should close stdin inside popen&quot; do
-      @provider.should_receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
-      @stdin.should_receive(:close).and_return(true)
-      @provider.load_current_resource
-    end
-
     it &quot;should read stdout of the ps command&quot; do
       @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
       @stdout.should_receive(:each_line).and_return(true)</diff>
      <filename>chef/spec/unit/provider/service/freebsd_service_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -159,12 +159,14 @@ describe Chef::Provider::Subversion do
   it &quot;runs the checkout command for action_checkout&quot; do
     expected_cmd = &quot;svn checkout -q  -r12345 http://svn.example.org/trunk/ /my/deploy/dir&quot;
     @provider.should_receive(:run_command).with(:command =&gt; expected_cmd)
+    @resource.should_receive(:updated=).at_least(1).times.with(true)
     @provider.action_checkout
   end
   
   it &quot;does a checkout for action_sync if there's no deploy dir&quot; do
     ::File.should_receive(:exist?).with(&quot;/my/deploy/dir/.svn&quot;).and_return(false)
     @provider.should_receive(:action_checkout)
+    @resource.should_receive(:updated=).at_least(1).times.with(true)
     @provider.action_sync
   end
   
@@ -172,6 +174,7 @@ describe Chef::Provider::Subversion do
     ::File.should_receive(:exist?).with(&quot;/my/deploy/dir/.svn&quot;).and_return(true)
     ::Dir.should_receive(:entries).with(&quot;/my/deploy/dir&quot;).and_return(['.','..'])
     @provider.should_receive(:action_checkout)
+    @resource.should_receive(:updated=).at_least(1).times.with(true)
     @provider.action_sync
   end
   
@@ -180,12 +183,14 @@ describe Chef::Provider::Subversion do
     ::Dir.should_receive(:entries).with(&quot;/my/deploy/dir&quot;).and_return(['.','..','the','app','exists'])
     expected_cmd = &quot;svn update -q  -r12345 /my/deploy/dir&quot;
     @provider.should_receive(:run_command).with(:command =&gt; expected_cmd)
+    @resource.should_receive(:updated=).at_least(1).times.with(true)
     @provider.action_sync
   end
   
   it &quot;runs the export_command on action_export&quot; do
     expected_cmd = &quot;svn export -q  -r12345 http://svn.example.org/trunk/ /my/deploy/dir&quot;
     @provider.should_receive(:run_command).with(:command =&gt; expected_cmd)
+    @resource.should_receive(:updated=).at_least(1).times.with(true)
     @provider.action_export
   end
   </diff>
      <filename>chef/spec/unit/provider/subversion_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -73,7 +73,6 @@ describe Chef::Resource::Deploy do
   resource_has_a_boolean_attribute(:migrate, :defaults_to=&gt;false)
   resource_has_a_boolean_attribute(:enable_submodules, :defaults_to=&gt;false)
   resource_has_a_boolean_attribute(:shallow_clone, :defaults_to=&gt;false)
-  resource_has_a_boolean_attribute(:force_deploy, :defaults_to=&gt;false)
   
   it &quot;uses the first argument as the deploy directory&quot; do
     @resource.deploy_to.should eql(&quot;/my/deploy/dir&quot;)</diff>
      <filename>chef/spec/unit/resource/deploy_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -20,333 +20,365 @@ require File.expand_path(File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;spec_helper&quot;))
 require 'uri'
 require 'net/https'
 
-describe Chef::REST, &quot;initialize method&quot; do
-  it &quot;should create a new Chef::REST&quot; do
-    Chef::REST.new(&quot;url&quot;).should be_kind_of(Chef::REST)
+describe Chef::REST do
+  before(:each) do
+    Chef::REST::CookieJar.stub!(:instance).and_return({})
+    @rest = Chef::REST.new(&quot;url&quot;, nil, nil)
   end
-end
 
-describe Chef::REST, &quot;get_rest method&quot; do
-  it &quot;should create a url from the path and base url&quot; do
-    URI.should_receive(:parse).with(&quot;url/monkey&quot;)
-    r = Chef::REST.new(&quot;url&quot;)
-    r.stub!(:run_request)
-    r.get_rest(&quot;monkey&quot;)
-  end
-  
-  it &quot;should call run_request :GET with the composed url object&quot; do
-    URI.stub!(:parse).and_return(true)
-    r = Chef::REST.new(&quot;url&quot;)
-    r.should_receive(:run_request).with(:GET, true, false, 10, false).and_return(true)
-    r.get_rest(&quot;monkey&quot;)
+  describe &quot;initialize&quot; do
+    it &quot;should create a new Chef::REST&quot; do
+      @rest.should be_kind_of(Chef::REST)
+    end
   end
-end
 
-describe Chef::REST, &quot;delete_rest method&quot; do
-  it &quot;should create a url from the path and base url&quot; do
-    URI.should_receive(:parse).with(&quot;url/monkey&quot;)
-    r = Chef::REST.new(&quot;url&quot;)
-    r.stub!(:run_request)
-    r.delete_rest(&quot;monkey&quot;)
-  end
-  
-  it &quot;should call run_request :DELETE with the composed url object&quot; do
-    URI.stub!(:parse).and_return(true)
-    r = Chef::REST.new(&quot;url&quot;)
-    r.should_receive(:run_request).with(:DELETE, true).and_return(true)
-    r.delete_rest(&quot;monkey&quot;)
-  end
-end
+  describe &quot;load_signing_key&quot; do
+    before(:each) do
+      @private_key = &lt;&lt;EOH
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAx8xAfO2BO8kUughpjWwHPN2rgDcES15PbMEGe6OdJgjFARkt
+FMdEusbGxmXKpk51Ggxi2P6ZYEoZfniZWt4qSt4i1vanDayRlJ1qoRCOaYj5cQS7
+gpHspHWqkY3HfGvx4svdutQ06o/gypx2QYfi68YrIUQexPiTUhsnP9FlgNt40Rl1
+YgBiIlJUk7d3q+1b/+POTNKPeyjGK9hoTloplbSx+cYdZgc4/YpU0eLBoHPuPv5l
+QD+Y8VNS39bvY2NWbCqhV508gExAK26FxXTDNpi2mTZmbRZ8U0PKrCgF6gBSeod5
+EdQnNgoZHmA2fzfPHWfJd2OEuMcNM7DWpPDizQIDAQABAoIBAAGVDYGvw9E8Y2yh
+umxDSb9ipgQK637JTWm4EZwTDKCLezvp/iBm/5VXE6XoknVEs8q0BGhhg8dubstA
+mz5L+hvDrJT1ORdzoWeC46BI6EfPrOIHPpDnJO+cevBSJh1HIZBBOw1KtuyQnSAd
+oxYbxGFHnXnS90dqDIie7G2l897UWoiQWNMLY+A+l5H4GLC+4Phq02pLd4OQwXA3
+Nd+3Nq69aOeccyfSDeeG7u35TKrjQPIxU210aR18d/0trR20BKsKbT30GPE1tQQd
+jm4uReSPttTQ+NjwBQKKYmO2F9b9MPzmQ7c+KycBRmf+IOgZeZ54JN0GzUXsDTjJ
++ZSgdgUCgYEA41aetBJwsKkF973gL54QCB5vFhRw3TdUgYhQgz04B5JGouGTSALy
+u1XtO6il65Zf6FwFSzXiggYYxTKyP/zwL88CQAVA7rleyhoZrw2bD6R2RZLivRba
+50rstltUbjevd96TagFY7i9gVHL9E6DKJH4unZfIM0Bl2IZQraqCR8MCgYEA4PzC
+FfUwiLa5drN6OVWZZfwxOeMbQUsYVeq7pHyeuvIe0euhcCLabBqfVt0pxqf1hem+
+l2+PnSKtvbI9siwt6WvJCtB3e/3aHOA3d6Y9TYxoyJAK007mRlQbbgqLzG83tZH2
+twO2tjo+h1+nv5yjE7aF9ItszegwTWsupvR+Ei8CgYAy0nt6MCEnLTIbV0RWANT+
+q6cT3Y/5tFPc/Vdab4YmEypdYWZmk9olzSjSzHoDN8PLEz9PuAUiIjDJbPLyYR5k
+4bdUDpicha5OKhWRz83Zal/SX+r2cLSRPmu6vKIcXbCJcKWt7g0uekLjvi0bhTeL
+fvX23yavZnceN7Czkkm7twKBgEFTgrNHdykrDRzXLhT5ssm2+UAani5ONKm1t3gi
+KyCS7rn7FevuYsdiz4M0Qk4JNLQGU6262dNBX3smBt32D/qnrj8ymo7o/WzG+bQH
+E+OxcjdSA6KpVRl0kGZaL49Td7SDxkQLkwDEVqWN87IiNAOkSq7f0N7UnTnNdkVJ
+1lVHAoGBANYgMoEj7gIJdch7hMdQcFfq9+4ntAAbsl3JFW+T9ChATn0XHAylP9ha
+ZaGlRrC7vxcF06vMe0HXyH1XVK3J9186zliTa4oDjkQ0D5X7Ga7KktLXAmQTysUH
+V3jwIQbAF6LqLUnGOq6rJzQxrWKvFt0mVDyuJzIJGSbnN/Sl5J6P
+-----END RSA PRIVATE KEY-----
+EOH
+      IO.stub!(:read).and_return(@private_key)
+    end
 
-describe Chef::REST, &quot;post_rest method&quot; do
-  it &quot;should create a url from the path and base url&quot; do
-    URI.should_receive(:parse).with(&quot;url/monkey&quot;)
-    r = Chef::REST.new(&quot;url&quot;)
-    r.stub!(:run_request)
-    r.post_rest(&quot;monkey&quot;, &quot;data&quot;)
-  end
-  
-  it &quot;should call run_request :POST with the composed url object and data&quot; do
-    URI.stub!(:parse).and_return(true)
-    r = Chef::REST.new(&quot;url&quot;)
-    r.should_receive(:run_request).with(:POST, true, &quot;data&quot;).and_return(true)
-    r.post_rest(&quot;monkey&quot;, &quot;data&quot;)
-  end
-end
+    it &quot;should return the contents of the key file&quot; do
+      File.stub!(:exists?).and_return(true)
+      File.stub!(:readable?).and_return(true)
+      @rest.load_signing_key(&quot;/tmp/keyfile.pem&quot;).should be(@private_key)
+    end
 
-describe Chef::REST, &quot;put_rest method&quot; do
-  it &quot;should create a url from the path and base url&quot; do
-    URI.should_receive(:parse).with(&quot;url/monkey&quot;)
-    r = Chef::REST.new(&quot;url&quot;)
-    r.stub!(:run_request)
-    r.put_rest(&quot;monkey&quot;, &quot;data&quot;)
-  end
-  
-  it &quot;should call run_request :PUT with the composed url object and data&quot; do
-    URI.stub!(:parse).and_return(true)
-    r = Chef::REST.new(&quot;url&quot;)
-    r.should_receive(:run_request).with(:PUT, true, &quot;data&quot;).and_return(true)
-    r.put_rest(&quot;monkey&quot;, &quot;data&quot;)
-  end
-end
+    it &quot;should raise a Chef::Exceptions::PrivateKeyMissing exception if the key cannot be found&quot; do
+      File.stub!(:exists?).and_return(false)
+      File.stub!(:readable?).and_return(true) #42!
+      lambda {
+        @rest.load_signing_key(&quot;/tmp/keyfile.pem&quot;)
+      }.should raise_error(Chef::Exceptions::PrivateKeyMissing)
+    end
 
-describe Chef::REST, &quot;run_request method&quot; do
-  before(:each) do
-    Chef::REST::CookieJar.stub!(:instance).and_return({})
-    @r = Chef::REST.new(&quot;url&quot;)
-    @url_mock = mock(&quot;URI&quot;, :null_object =&gt; true)
-    @url_mock.stub!(:host).and_return(&quot;one&quot;)
-    @url_mock.stub!(:port).and_return(&quot;80&quot;)
-    @url_mock.stub!(:path).and_return(&quot;/&quot;)
-    @url_mock.stub!(:query).and_return(&quot;foo=bar&quot;)
-    @url_mock.stub!(:scheme).and_return(&quot;https&quot;)
-    @url_mock.stub!(:user).and_return(nil)
-    @url_mock.stub!(:password).and_return(nil)
-    @url_mock.stub!(:to_s).and_return(&quot;https://one:80/?foo=bar&quot;)
-    @http_response_mock = mock(&quot;Net::HTTPSuccess&quot;, :null_object =&gt; true)
-    @http_response_mock.stub!(:kind_of?).with(Net::HTTPSuccess).and_return(true)
-    @http_response_mock.stub!(:body).and_return(&quot;ninja&quot;)
-    @http_response_mock.stub!(:error!).and_return(true)
-    @http_response_mock.stub!(:header).and_return({ 'Content-Length' =&gt; &quot;5&quot; })
-    @http_mock = mock(&quot;Net::HTTP&quot;, :null_object =&gt; true)
-    @http_mock.stub!(:verify_mode=).and_return(true)
-    @http_mock.stub!(:read_timeout=).and_return(true)
-    @http_mock.stub!(:use_ssl=).with(true).and_return(true)
-    @data_mock = mock(&quot;Data&quot;, :null_object =&gt; true)
-    @data_mock.stub!(:to_json).and_return('{ &quot;one&quot;: &quot;two&quot; }')
-    @request_mock = mock(&quot;Request&quot;, :null_object =&gt; true)
-    @request_mock.stub!(:body=).and_return(true)
-    @request_mock.stub!(:method).and_return(true)
-    @request_mock.stub!(:path).and_return(true)
-    @http_mock.stub!(:request).and_return(@http_response_mock)
-    @tf_mock = mock(Tempfile, { :print =&gt; true, :close =&gt; true, :write =&gt; true })
-    Tempfile.stub!(:new).with(&quot;chef-rest&quot;).and_return(@tf_mock)
-  end
-  
-  def do_run_request(method=:GET, data=false, limit=10, raw=false)
-    Net::HTTP.stub!(:new).and_return(@http_mock)
-    @r.run_request(method, @url_mock, data, limit, raw)
+    it &quot;should raise a Chef::Exceptions::PrivateKeyMissing exception if the key cannot be read&quot; do
+      File.stub!(:exists?).and_return(true)
+      File.stub!(:readable?).and_return(false)
+      lambda {
+        @rest.load_signing_key(&quot;/tmp/keyfile.pem&quot;)
+      }.should raise_error(Chef::Exceptions::PrivateKeyMissing)
+    end
   end
-  
-  it &quot;should raise an exception if the redirect limit is 0&quot; do
-    lambda { @r.run_request(:GET, &quot;/&quot;, false, 0)}.should raise_error(ArgumentError)
+
+  describe &quot;get_rest&quot; do
+    it &quot;should create a url from the path and base url&quot; do
+      URI.should_receive(:parse).with(&quot;url/monkey&quot;)
+      @rest.stub!(:run_request)
+      @rest.get_rest(&quot;monkey&quot;)
+    end
+    
+    it &quot;should call run_request :GET with the composed url object&quot; do
+      URI.stub!(:parse).and_return(true)
+      @rest.should_receive(:run_request).with(:GET, true, {}, false, 10, false).and_return(true)
+      @rest.get_rest(&quot;monkey&quot;)
+    end
   end
 
-  it &quot;should not fail if URI contains %d characters&quot; do
-    @http_response_mock.stub!(:read_body).and_yield(&quot;ninja&quot;)
-    @url_mock.stub!(:path).and_return(&quot;/myfile?Expires=1247484042&amp;Signature=hpK%2BbHchAmUCErdz1yCBPazzGRQ%3D&quot;)
-    @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
-    @http_response_mock.should_receive(:read_body).and_return(true)
-    do_run_request(:GET, false, 10, true)
+  describe &quot;delete_rest&quot; do
+    it &quot;should create a url from the path and base url&quot; do
+      URI.should_receive(:parse).with(&quot;url/monkey&quot;)
+      @rest.stub!(:run_request)
+      @rest.delete_rest(&quot;monkey&quot;)
+    end
+    
+    it &quot;should call run_request :DELETE with the composed url object&quot; do
+      URI.stub!(:parse).and_return(true)
+      @rest.should_receive(:run_request).with(:DELETE, true, {}).and_return(true)
+      @rest.delete_rest(&quot;monkey&quot;)
+    end
   end
-  
-  it &quot;should use SSL if the url starts with https&quot; do
-    @url_mock.should_receive(:scheme).and_return(&quot;https&quot;)
-    @http_mock.should_receive(:use_ssl=).with(true).and_return(true)
-    do_run_request
+
+  describe &quot;post_rest&quot; do
+    it &quot;should create a url from the path and base url&quot; do
+      URI.should_receive(:parse).with(&quot;url/monkey&quot;)
+      @rest.stub!(:run_request)
+      @rest.post_rest(&quot;monkey&quot;, &quot;data&quot;)
+    end
+    
+    it &quot;should call run_request :POST with the composed url object and data&quot; do
+      URI.stub!(:parse).and_return(true)
+      @rest.should_receive(:run_request).with(:POST, true, {}, &quot;data&quot;).and_return(true)
+      @rest.post_rest(&quot;monkey&quot;, &quot;data&quot;)
+    end
   end
-  
-  it &quot;should set the OpenSSL Verify Mode to verify_none if requested&quot; do
-    @http_mock.should_receive(:verify_mode=).and_return(true)
-    do_run_request
+
+  describe &quot;put_rest&quot; do
+    it &quot;should create a url from the path and base url&quot; do
+      URI.should_receive(:parse).with(&quot;url/monkey&quot;)
+      @rest.stub!(:run_request)
+      @rest.put_rest(&quot;monkey&quot;, &quot;data&quot;)
+    end
+    
+    it &quot;should call run_request :PUT with the composed url object and data&quot; do
+      URI.stub!(:parse).and_return(true)
+      @rest.should_receive(:run_request).with(:PUT, true, {}, &quot;data&quot;).and_return(true)
+      @rest.put_rest(&quot;monkey&quot;, &quot;data&quot;)
+    end
   end
-  
-  describe &quot;with a client SSL cert&quot; do
+
+  describe Chef::REST, &quot;run_request method&quot; do
     before(:each) do
-      Chef::Config[:ssl_client_cert] = &quot;/etc/chef/client-cert.pem&quot;
-      Chef::Config[:ssl_client_key] = &quot;/etc/chef/client-cert.key&quot;
-      File.stub!(:exists?).with(&quot;/etc/chef/client-cert.pem&quot;).and_return(true)
-      File.stub!(:exists?).with(&quot;/etc/chef/client-cert.key&quot;).and_return(true)
-      File.stub!(:read).with(&quot;/etc/chef/client-cert.pem&quot;).and_return(&quot;monkey magic client&quot;)
-      File.stub!(:read).with(&quot;/etc/chef/client-cert.key&quot;).and_return(&quot;monkey magic key&quot;)
-      OpenSSL::X509::Certificate.stub!(:new).and_return(&quot;monkey magic client data&quot;)
-      OpenSSL::PKey::RSA.stub!(:new).and_return(&quot;monkey magic key data&quot;)
+      @url_mock = mock(&quot;URI&quot;, :null_object =&gt; true)
+      @url_mock.stub!(:host).and_return(&quot;one&quot;)
+      @url_mock.stub!(:port).and_return(&quot;80&quot;)
+      @url_mock.stub!(:path).and_return(&quot;/&quot;)
+      @url_mock.stub!(:query).and_return(&quot;foo=bar&quot;)
+      @url_mock.stub!(:scheme).and_return(&quot;https&quot;)
+      @url_mock.stub!(:to_s).and_return(&quot;https://one:80/?foo=bar&quot;)
+      @http_response_mock = mock(&quot;Net::HTTPSuccess&quot;, :null_object =&gt; true)
+      @http_response_mock.stub!(:kind_of?).with(Net::HTTPSuccess).and_return(true)
+      @http_response_mock.stub!(:body).and_return(&quot;ninja&quot;)
+      @http_response_mock.stub!(:error!).and_return(true)
+      @http_response_mock.stub!(:header).and_return({ 'Content-Length' =&gt; &quot;5&quot; })
+      @http_mock = mock(&quot;Net::HTTP&quot;, :null_object =&gt; true)
+      @http_mock.stub!(:verify_mode=).and_return(true)
+      @http_mock.stub!(:read_timeout=).and_return(true)
+      @http_mock.stub!(:use_ssl=).with(true).and_return(true)
+      @data_mock = mock(&quot;Data&quot;, :null_object =&gt; true)
+      @data_mock.stub!(:to_json).and_return('{ &quot;one&quot;: &quot;two&quot; }')
+      @request_mock = mock(&quot;Request&quot;, :null_object =&gt; true)
+      @request_mock.stub!(:body=).and_return(true)
+      @request_mock.stub!(:method).and_return(true)
+      @request_mock.stub!(:path).and_return(true)
+      @http_mock.stub!(:request).and_return(@http_response_mock)
+      @tf_mock = mock(Tempfile, { :print =&gt; true, :close =&gt; true, :write =&gt; true })
+      Tempfile.stub!(:new).with(&quot;chef-rest&quot;).and_return(@tf_mock)
     end
-
-    it &quot;should check that the client cert file exists&quot; do
-      File.should_receive(:exists?).with(&quot;/etc/chef/client-cert.pem&quot;).and_return(true)
+    
+    def do_run_request(method=:GET, data=false, limit=10, raw=false)
+      Net::HTTP.stub!(:new).and_return(@http_mock)
+      @rest.run_request(method, @url_mock, {}, data, limit, raw)
+    end
+    
+    it &quot;should raise an exception if the redirect limit is 0&quot; do
+      lambda { @rest.run_request(:GET, &quot;/&quot;, {}, false, 0)}.should raise_error(ArgumentError)
+    end
+    
+    it &quot;should use SSL if the url starts with https&quot; do
+      @url_mock.should_receive(:scheme).and_return(&quot;https&quot;)
+      @http_mock.should_receive(:use_ssl=).with(true).and_return(true)
       do_run_request
     end
-
-    it &quot;should read the cert file&quot; do
-      File.should_receive(:read).with(&quot;/etc/chef/client-cert.pem&quot;).and_return(&quot;monkey magic client&quot;)
+    
+    it &quot;should set the OpenSSL Verify Mode to verify_none if requested&quot; do
+      @http_mock.should_receive(:verify_mode=).and_return(true)
       do_run_request
     end
+    
+    describe &quot;with a client SSL cert&quot; do
+      before(:each) do
+        Chef::Config[:ssl_client_cert] = &quot;/etc/chef/client-cert.pem&quot;
+        Chef::Config[:ssl_client_key] = &quot;/etc/chef/client-cert.key&quot;
+        File.stub!(:exists?).with(&quot;/etc/chef/client-cert.pem&quot;).and_return(true)
+        File.stub!(:exists?).with(&quot;/etc/chef/client-cert.key&quot;).and_return(true)
+        File.stub!(:read).with(&quot;/etc/chef/client-cert.pem&quot;).and_return(&quot;monkey magic client&quot;)
+        File.stub!(:read).with(&quot;/etc/chef/client-cert.key&quot;).and_return(&quot;monkey magic key&quot;)
+        OpenSSL::X509::Certificate.stub!(:new).and_return(&quot;monkey magic client data&quot;)
+        OpenSSL::PKey::RSA.stub!(:new).and_return(&quot;monkey magic key data&quot;)
+      end
+
+      it &quot;should check that the client cert file exists&quot; do
+        File.should_receive(:exists?).with(&quot;/etc/chef/client-cert.pem&quot;).and_return(true)
+        do_run_request
+      end
+
+      it &quot;should read the cert file&quot; do
+        File.should_receive(:read).with(&quot;/etc/chef/client-cert.pem&quot;).and_return(&quot;monkey magic client&quot;)
+        do_run_request
+      end
+
+      it &quot;should read the cert into OpenSSL&quot; do
+        OpenSSL::X509::Certificate.should_receive(:new).and_return(&quot;monkey magic client data&quot;)
+        do_run_request
+      end
+
+      it &quot;should set the cert&quot; do
+        @http_mock.should_receive(:cert=).and_return(true)
+        do_run_request
+      end
+
+      it &quot;should read the key file&quot; do
+        File.should_receive(:read).with(&quot;/etc/chef/client-cert.key&quot;).and_return(&quot;monkey magic key&quot;)
+        do_run_request
+      end
+
+      it &quot;should read the key into OpenSSL&quot; do
+        OpenSSL::PKey::RSA.should_receive(:new).and_return(&quot;monkey magic key data&quot;)
+        do_run_request
+      end
+
+      it &quot;should set the key&quot; do
+        @http_mock.should_receive(:key=).and_return(true)
+        do_run_request
+      end
 
-    it &quot;should read the cert into OpenSSL&quot; do
-      OpenSSL::X509::Certificate.should_receive(:new).and_return(&quot;monkey magic client data&quot;)
-      do_run_request
     end
 
-    it &quot;should set the cert&quot; do
-      @http_mock.should_receive(:cert=).and_return(true)
+    it &quot;should set a read timeout based on the rest_timeout config option&quot; do
+      Chef::Config[:rest_timeout] = 10
+      @http_mock.should_receive(:read_timeout=).with(10).and_return(true)
       do_run_request
     end
-
-    it &quot;should read the key file&quot; do
-      File.should_receive(:read).with(&quot;/etc/chef/client-cert.key&quot;).and_return(&quot;monkey magic key&quot;)
+    
+    it &quot;should set the cookie for this request if one exists for the given host:port&quot; do
+      @rest.cookies = { &quot;#{@url_mock.host}:#{@url_mock.port}&quot; =&gt; &quot;cookie monster&quot; }
+      Net::HTTP::Get.should_receive(:new).with(&quot;/?foo=bar&quot;, 
+        { 'Accept' =&gt; 'application/json', 'Cookie' =&gt; 'cookie monster' }
+      ).and_return(@request_mock)
       do_run_request
+      @rest.cookies = Hash.new
     end
-
-    it &quot;should read the key into OpenSSL&quot; do
-      OpenSSL::PKey::RSA.should_receive(:new).and_return(&quot;monkey magic key data&quot;)
+    
+    it &quot;should build a new HTTP GET request&quot; do
+      Net::HTTP::Get.should_receive(:new).with(&quot;/?foo=bar&quot;, 
+        { 'Accept' =&gt; 'application/json' }
+      ).and_return(@request_mock)
       do_run_request
     end
-
-    it &quot;should set the key&quot; do
-      @http_mock.should_receive(:key=).and_return(true)
+    
+    it &quot;should build a new HTTP POST request&quot; do
+      Net::HTTP::Post.should_receive(:new).with(&quot;/?foo=bar&quot;, 
+        { 'Accept' =&gt; 'application/json', &quot;Content-Type&quot; =&gt; 'application/json' }
+      ).and_return(@request_mock)
+      do_run_request(:POST, @data_mock)
+    end
+    
+    it &quot;should build a new HTTP PUT request&quot; do
+      Net::HTTP::Put.should_receive(:new).with(&quot;/?foo=bar&quot;, 
+        { 'Accept' =&gt; 'application/json', &quot;Content-Type&quot; =&gt; 'application/json' }
+      ).and_return(@request_mock)
+      do_run_request(:PUT, @data_mock)
+    end
+    
+    it &quot;should build a new HTTP DELETE request&quot; do
+      Net::HTTP::Delete.should_receive(:new).with(&quot;/?foo=bar&quot;, 
+        { 'Accept' =&gt; 'application/json' }
+      ).and_return(@request_mock)
+      do_run_request(:DELETE)
+    end
+    
+    it &quot;should raise an error if the method is not GET/PUT/POST/DELETE&quot; do
+      lambda { do_run_request(:MONKEY) }.should raise_error(ArgumentError)
+    end
+    
+    it &quot;should run an http request&quot; do
+      @http_mock.should_receive(:request).and_return(@http_response_mock)
       do_run_request
     end
-
-  end
-
-  it &quot;should set a read timeout based on the rest_timeout config option&quot; do
-    Chef::Config[:rest_timeout] = 10
-    @http_mock.should_receive(:read_timeout=).with(10).and_return(true)
-    do_run_request
-  end
-  
-  it &quot;should set the cookie for this request if one exists for the given host:port&quot; do
-    @r.cookies = { &quot;#{@url_mock.host}:#{@url_mock.port}&quot; =&gt; &quot;cookie monster&quot; }
-    Net::HTTP::Get.should_receive(:new).with(&quot;/?foo=bar&quot;, 
-      { 'Accept' =&gt; 'application/json', 'Cookie' =&gt; 'cookie monster' }
-    ).and_return(@request_mock)
-    do_run_request
-  end
-  
-  it &quot;should build a new HTTP GET request&quot; do
-    Net::HTTP::Get.should_receive(:new).with(&quot;/?foo=bar&quot;, 
-      { 'Accept' =&gt; 'application/json' }
-    ).and_return(@request_mock)
-    do_run_request
-  end
-  
-  it &quot;should build a new HTTP POST request&quot; do
-    Net::HTTP::Post.should_receive(:new).with(&quot;/&quot;, 
-      { 'Accept' =&gt; 'application/json', &quot;Content-Type&quot; =&gt; 'application/json' }
-    ).and_return(@request_mock)
-    do_run_request(:POST, @data_mock)
-  end
-  
-  it &quot;should build a new HTTP PUT request&quot; do
-    Net::HTTP::Put.should_receive(:new).with(&quot;/&quot;, 
-      { 'Accept' =&gt; 'application/json', &quot;Content-Type&quot; =&gt; 'application/json' }
-    ).and_return(@request_mock)
-    do_run_request(:PUT, @data_mock)
-  end
-  
-  it &quot;should build a new HTTP DELETE request&quot; do
-    Net::HTTP::Delete.should_receive(:new).with(&quot;/?foo=bar&quot;, 
-      { 'Accept' =&gt; 'application/json' }
-    ).and_return(@request_mock)
-    do_run_request(:DELETE)
-  end
-  
-  describe &quot;with HTTP Basic Authentication info in the URL&quot; do
-    before(:each) do
-      @url_mock.stub!(:user).and_return('frodo')
-      @url_mock.stub!(:password).and_return('odorf')
+    
+    it &quot;should return the body of the response on success&quot; do
+      do_run_request.should eql(&quot;ninja&quot;)
     end
-
-    %w(Get Post Put Delete).each do |verb|
-      it &quot;should authenticate HTTP #{verb.upcase} requests&quot; do
-        Net::HTTP::const_get(verb).stub!(:new).and_return(@request_mock)
-        @request_mock.should_receive(:basic_auth).with('frodo', 'odorf')
-        do_run_request(verb.upcase.to_sym)
-      end
+    
+    it &quot;should inflate the body as to an object if JSON is returned&quot; do
+      @http_response_mock.stub!(:[]).with('content-type').and_return(&quot;application/json&quot;)
+      JSON.should_receive(:parse).with(&quot;ninja&quot;).and_return(true)
+      do_run_request
+    end
+    
+    it &quot;should call run_request again on a Redirect response&quot; do
+      @http_response_mock.stub!(:kind_of?).with(Net::HTTPSuccess).and_return(false)
+      @http_response_mock.stub!(:kind_of?).with(Net::HTTPFound).and_return(true)
+      @http_response_mock.stub!(:[]).with('location').and_return(@url_mock.path)
+      lambda { do_run_request(method=:GET, data=false, limit=1) }.should raise_error(ArgumentError)
     end
-  end
 
-  it &quot;should raise an error if the method is not GET/PUT/POST/DELETE&quot; do
-    lambda { do_run_request(:MONKEY) }.should raise_error(ArgumentError)
-  end
-  
-  it &quot;should run an http request&quot; do
-    @http_mock.should_receive(:request).and_return(@http_response_mock)
-    do_run_request
-  end
-  
-  it &quot;should return the body of the response on success&quot; do
-    do_run_request.should eql(&quot;ninja&quot;)
-  end
-  
-  it &quot;should inflate the body as to an object if JSON is returned&quot; do
-    @http_response_mock.stub!(:[]).with('content-type').and_return(&quot;application/json&quot;)
-    JSON.should_receive(:parse).with(&quot;ninja&quot;).and_return(true)
-    do_run_request
-  end
-  
-  it &quot;should call run_request again on a Redirect response&quot; do
-    @http_response_mock.stub!(:kind_of?).with(Net::HTTPSuccess).and_return(false)
-    @http_response_mock.stub!(:kind_of?).with(Net::HTTPFound).and_return(true)
-    @http_response_mock.stub!(:[]).with('location').and_return(@url_mock.path)
-    lambda { do_run_request(method=:GET, data=false, limit=1) }.should raise_error(ArgumentError)
-  end
+    it &quot;should call run_request again on a Permanent Redirect response&quot; do
+      @http_response_mock.stub!(:kind_of?).with(Net::HTTPSuccess).and_return(false)
+      @http_response_mock.stub!(:kind_of?).with(Net::HTTPFound).and_return(false)
+      @http_response_mock.stub!(:kind_of?).with(Net::HTTPMovedPermanently).and_return(true)
+      @http_response_mock.stub!(:[]).with('location').and_return(@url_mock.path)
+      lambda { do_run_request(method=:GET, data=false, limit=1) }.should raise_error(ArgumentError)
+    end
+    
+    it &quot;should raise an exception on an unsuccessful request&quot; do
+      @http_response_mock.stub!(:kind_of?).with(Net::HTTPSuccess).and_return(false)
+      @http_response_mock.stub!(:kind_of?).with(Net::HTTPFound).and_return(false)
+      @http_response_mock.stub!(:kind_of?).with(Net::HTTPMovedPermanently).and_return(false)
+      @http_response_mock.should_receive(:error!)
+      do_run_request
+    end
+    
+    it &quot;should build a new HTTP GET request without the application/json accept header for raw reqs&quot; do
+      Net::HTTP::Get.should_receive(:new).with(&quot;/?foo=bar&quot;, {}).and_return(@request_mock)
+      do_run_request(:GET, false, 10, true)
+    end
+    
+    it &quot;should create a tempfile for the output of a raw request&quot; do
+      @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
+      Tempfile.should_receive(:new).with(&quot;chef-rest&quot;).and_return(@tf_mock)
+      do_run_request(:GET, false, 10, true).should eql(@tf_mock)    
+    end
+    
+    it &quot;should read the body of the response in chunks on a raw request&quot; do
+      @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
+      @http_response_mock.should_receive(:read_body).and_return(true)
+      do_run_request(:GET, false, 10, true)
+    end
+    
+    it &quot;should populate the tempfile with the value of the raw request&quot; do
+      @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
+      @http_response_mock.stub!(:read_body).and_yield(&quot;ninja&quot;)
+      @tf_mock.should_receive(:write, &quot;ninja&quot;).once.and_return(true)
+      do_run_request(:GET, false, 10, true)
+    end
+    
+    it &quot;should close the tempfile if we're doing a raw request&quot; do
+      @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
+      @tf_mock.should_receive(:close).once.and_return(true)
+      do_run_request(:GET, false, 10, true)
+    end
+    
+    it &quot;should not raise a divide by zero exception if the size is 0&quot; do
+      @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
+      @http_response_mock.stub!(:header).and_return({ 'Content-Length' =&gt; &quot;5&quot; })
+      @http_response_mock.stub!(:read_body).and_yield('')
+      lambda { do_run_request(:GET, false, 10, true) }.should_not raise_error(ZeroDivisionError)
+    end
+    
+    it &quot;should not raise a divide by zero exception if the Content-Length is 0&quot; do
+      @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
+      @http_response_mock.stub!(:header).and_return({ 'Content-Length' =&gt; &quot;0&quot; })
+      @http_response_mock.stub!(:read_body).and_yield(&quot;ninja&quot;)
+      lambda { do_run_request(:GET, false, 10, true) }.should_not raise_error(ZeroDivisionError)
+    end
+    
+    it &quot;should call read_body without a block if the request is not raw&quot; do
+      @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
+      @http_response_mock.should_receive(:read_body)
+      do_run_request(:GET, false, 10, false)
+    end
 
-  it &quot;should call run_request again on a Permanent Redirect response&quot; do
-    @http_response_mock.stub!(:kind_of?).with(Net::HTTPSuccess).and_return(false)
-    @http_response_mock.stub!(:kind_of?).with(Net::HTTPFound).and_return(false)
-    @http_response_mock.stub!(:kind_of?).with(Net::HTTPMovedPermanently).and_return(true)
-    @http_response_mock.stub!(:[]).with('location').and_return(@url_mock.path)
-    lambda { do_run_request(method=:GET, data=false, limit=1) }.should raise_error(ArgumentError)
-  end
-  
-  it &quot;should raise an exception on an unsuccessful request&quot; do
-    @http_response_mock.stub!(:kind_of?).with(Net::HTTPSuccess).and_return(false)
-    @http_response_mock.stub!(:kind_of?).with(Net::HTTPFound).and_return(false)
-    @http_response_mock.stub!(:kind_of?).with(Net::HTTPMovedPermanently).and_return(false)
-    @http_response_mock.should_receive(:error!)
-    do_run_request
-  end
-  
-  it &quot;should build a new HTTP GET request without the application/json accept header for raw reqs&quot; do
-    Net::HTTP::Get.should_receive(:new).with(&quot;/?foo=bar&quot;, {}).and_return(@request_mock)
-    do_run_request(:GET, false, 10, true)
-  end
-  
-  it &quot;should create a tempfile for the output of a raw request&quot; do
-    @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
-    Tempfile.should_receive(:new).with(&quot;chef-rest&quot;).and_return(@tf_mock)
-    do_run_request(:GET, false, 10, true).should eql(@tf_mock)    
-  end
-  
-  it &quot;should read the body of the response in chunks on a raw request&quot; do
-    @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
-    @http_response_mock.should_receive(:read_body).and_return(true)
-    do_run_request(:GET, false, 10, true)
-  end
-  
-  it &quot;should populate the tempfile with the value of the raw request&quot; do
-    @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
-    @http_response_mock.stub!(:read_body).and_yield(&quot;ninja&quot;)
-    @tf_mock.should_receive(:write, &quot;ninja&quot;).once.and_return(true)
-    do_run_request(:GET, false, 10, true)
-  end
-  
-  it &quot;should close the tempfile if we're doing a raw request&quot; do
-    @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
-    @tf_mock.should_receive(:close).once.and_return(true)
-    do_run_request(:GET, false, 10, true)
-  end
-  
-  it &quot;should not raise a divide by zero exception if the size is 0&quot; do
-    @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
-    @http_response_mock.stub!(:header).and_return({ 'Content-Length' =&gt; &quot;5&quot; })
-    @http_response_mock.stub!(:read_body).and_yield('')
-    lambda { do_run_request(:GET, false, 10, true) }.should_not raise_error(ZeroDivisionError)
-  end
-  
-  it &quot;should not raise a divide by zero exception if the Content-Length is 0&quot; do
-    @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
-    @http_response_mock.stub!(:header).and_return({ 'Content-Length' =&gt; &quot;0&quot; })
-    @http_response_mock.stub!(:read_body).and_yield(&quot;ninja&quot;)
-    lambda { do_run_request(:GET, false, 10, true) }.should_not raise_error(ZeroDivisionError)
-  end
-  
-  it &quot;should call read_body without a block if the request is not raw&quot; do
-    @http_mock.stub!(:request).and_yield(@http_response_mock).and_return(@http_response_mock)
-    @http_response_mock.should_receive(:read_body)
-    do_run_request(:GET, false, 10, false)
   end
 
 end
+</diff>
      <filename>chef/spec/unit/rest_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -147,7 +147,7 @@ describe Chef::RunList do
 
       Chef::Role.stub!(:from_disk).and_return(@role)
       Chef::Role.stub!(:load).and_return(@role)
-      @rest = mock(&quot;Chef::REST&quot;, { :get_rest =&gt; @role })
+      @rest = mock(&quot;Chef::REST&quot;, { :get_rest =&gt; @role, :url =&gt; &quot;/&quot; })
       Chef::REST.stub!(:new).and_return(@rest)
       
       @run_list &lt;&lt; &quot;role[stubby]&quot;
@@ -175,7 +175,7 @@ describe Chef::RunList do
 
     describe &quot;from couchdb&quot; do
       it &quot;should load the role from couchdb&quot; do
-        Chef::Role.should_receive(:load).with(&quot;stubby&quot;)
+        Chef::Role.should_receive(:cdb_load).and_return(@role)
         @run_list.expand(&quot;couchdb&quot;)
       end
     end</diff>
      <filename>chef/spec/unit/run_list_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,7 @@ task :default =&gt; :spec
 
 desc &quot;Run all specs in spec directory&quot;
 Spec::Rake::SpecTask.new(:spec) do |t|
-  t.spec_opts = ['--options', &quot;\&quot;#{CHEF_ROOT}/spec/spec.opts\&quot;&quot;]
+  t.spec_opts = ['--format', 'specdoc', '--options', &quot;\&quot;#{CHEF_ROOT}/spec/spec.opts\&quot;&quot;]
   t.spec_files = FileList['spec/**/*_spec.rb']
 end
 </diff>
      <filename>chef/tasks/rspec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,22 +1,46 @@
 default: -f pretty features -r features/steps -r features/support 
-api: --tags api --format pretty -r features/steps -r features/support features 
-api_roles: --tags roles --format pretty -r features/steps -r features/support features
+api: --tags @api --format pretty -r features/steps -r features/support features 
+api_cookbooks: --tags @api,@cookbooks --format pretty -r features/steps -r features/support features 
+api_clients: --tags @api_clients --format pretty -r features/steps -r features/support features
+api_clients_create: --tags clients_create --format pretty -r features/steps -r features/support features
+api_clients_delete: --tags clients_delete --format pretty -r features/steps -r features/support features
+api_clients_list: --tags clients_list --format pretty -r features/steps -r features/support features
+api_clients_show: --tags clients_show --format pretty -r features/steps -r features/support features
+api_clients_update: --tags clients_update --format pretty -r features/steps -r features/support features
+api_roles: --tags @api_roles --format pretty -r features/steps -r features/support features
 api_roles_create: --tags roles_create --format pretty -r features/steps -r features/support features
 api_roles_delete: --tags roles_delete --format pretty -r features/steps -r features/support features
 api_roles_list: --tags roles_list --format pretty -r features/steps -r features/support features
 api_roles_show: --tags roles_show --format pretty -r features/steps -r features/support features
 api_roles_update: --tags roles_update --format pretty -r features/steps -r features/support features
-api_nodes: --tags nodes --format pretty -r features/steps -r features/support features
+api_nodes: --tags @api_nodes --format pretty -r features/steps -r features/support features
+api_nodes_sync: --tags @cookbook_sync --format pretty -r features/steps -r features/support features
 api_nodes_create: --tags nodes_create --format pretty -r features/steps -r features/support features
 api_nodes_delete: --tags nodes_delete --format pretty -r features/steps -r features/support features
 api_nodes_list: --tags nodes_list --format pretty -r features/steps -r features/support features
 api_nodes_show: --tags nodes_show --format pretty -r features/steps -r features/support features
 api_nodes_update: --tags nodes_update --format pretty -r features/steps -r features/support features
-client: --tags client --format pretty -r features/steps -r features/support features 
+api_data: --tags @api_data --format pretty -r features/steps -r features/support features 
+api_data_delete: --tags @api_data_delete --format pretty -r features/steps -r features/support features 
+api_data_item: --tags @api_data_item --format pretty -r features/steps -r features/support features 
+api_search: --tags @api_search --format pretty -r features/steps -r features/support features 
+api_search_list: --tags @api_search_list --format pretty -r features/steps -r features/support features 
+api_search_show: --tags @api_search_show --format pretty -r features/steps -r features/support features 
+client: --tags @client --format pretty -r features/steps -r features/support features 
 client_roles: --tags client_roles --format pretty -r features/steps -r features/support features 
-search: --tags search --format pretty -r features/steps -r features/support features 
-language: --tags language --format pretty -r features/steps -r features/support features 
+search: --tags @search --format pretty -r features/steps -r features/support features 
+provider: --tags @provider --format pretty -r features/steps -r features/support features 
+provider_directory: --tags @provider_directory --format pretty -r features/steps -r features/support features 
+provider_deploy: --tags @provider_deploy --format pretty -r features/steps -r features/support features 
+provider_execute: --tags @provider_execute --format pretty -r features/steps -r features/support features 
+provider_file: --tags @provider_file --format pretty -r features/steps -r features/support features 
+provider_template: --tags template --format pretty -r features/steps -r features/support features
+provider_remote_file: --tags @remote_file --format pretty -r features/steps -r features/support features 
+provider_package_macports: --tags @macports --format pretty -r features/steps -r features/support features 
+language: --tags @language --format pretty -r features/steps -r features/support features 
+client_run_interval: --tags client_run_interval --format pretty -r features/steps -r features/support features
 recipe_inclusion: --tags recipe_inclusion --format pretty -r features/steps -r features/support features 
+cookbooks: --tags @cookbooks --format pretty -r features/steps -r features/support features 
 provider_remote_file: --tags provider,remote_file --format pretty -r features/steps -r features/support features 
 provider_git: --tags provider,git --format pretty -r features/steps -r features/support features 
 provider_template: --tags template --format pretty -r features/steps -r features/support features</diff>
      <filename>cucumber.yml</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-@api @nodes @nodes_create
+@api @api_nodes @nodes_create
 Feature: Create a node via the REST API
   In order to create nodes programatically 
   As a Devleoper
@@ -7,19 +7,19 @@ Feature: Create a node via the REST API
   Scenario: Create a new node 
     Given a 'registration' named 'bobo' exists
       And a 'node' named 'webserver'
-     When I authenticate as 'bobo'
-      And I 'POST' the 'node' to the path '/nodes' 
+     When I 'POST' the 'node' to the path '/nodes' 
       And the inflated responses key 'uri' should match '^http://.+/nodes/webserver$'
 
   Scenario: Create a node that already exists
     Given a 'registration' named 'bobo' exists
       And an 'node' named 'webserver'
-     When I authenticate as 'bobo'
-      And I 'POST' the 'node' to the path '/nodes' 
+     When I 'POST' the 'node' to the path '/nodes' 
       And I 'POST' the 'node' to the path '/nodes' 
      Then I should get a '403 &quot;Forbidden&quot;' exception
-
-  Scenario: Create a new node without authenticating
-    Given a 'node' named 'webserver'
-     When I 'POST' the 'node' to the path '/nodes' 
+  
+  Scenario: Create a node with a wrong private key
+    Given a 'registration' named 'bobo' exists
+      And an 'node' named 'webserver'
+     When I 'POST' the 'node' to the path '/nodes' using a wrong private key
      Then I should get a '401 &quot;Unauthorized&quot;' exception
+</diff>
      <filename>features/api/nodes/create_node_api.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-@api @nodes @nodes_delete
+@api @api_nodes @nodes_delete
 Feature: Delete a node via the REST API 
   In order to remove a node 
   As a Developer 
@@ -7,19 +7,24 @@ Feature: Delete a node via the REST API
   Scenario: Delete a node 
     Given a 'registration' named 'bobo' exists
       And a 'node' named 'webserver' exists
-     When I authenticate as 'bobo'
-      And I 'DELETE' the path '/nodes/webserver'
+     When I 'DELETE' the path '/nodes/webserver'
      Then the inflated response should respond to 'name' with 'webserver' 
 
   Scenario: Delete a node that does not exist
     Given a 'registration' named 'bobo' exists
       And there are no nodes 
-     When I authenticate as 'bobo'
      When I 'DELETE' the path '/nodes/webserver'
      Then I should get a '404 &quot;Not Found&quot;' exception
 
-  Scenario: Delete a node without authenticating 
-    Given a 'node' named 'webserver'
+  Scenario: Delete a node with a wrong private key
+    Given a 'registration' named 'bobo' exists
+      And a 'node' named 'webserver' exists
+     When I 'DELETE' the path '/nodes/webserver' using a wrong private key
+     Then I should get a '401 &quot;Unauthorized&quot;' exception
+
+  Scenario: Delete a node as a when I am not an admin
+    Given a 'registration' named 'not_admin' exists
+      And a 'node' named 'webserver' exists
      When I 'DELETE' the path '/nodes/webserver'
      Then I should get a '401 &quot;Unauthorized&quot;' exception
 </diff>
      <filename>features/api/nodes/delete_node_api.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-@api @nodes @nodes_list
+@api @api_nodes @nodes_list
 Feature: List nodes via the REST API
   In order to know what nodes exists programatically
   As a Developer
@@ -7,28 +7,26 @@ Feature: List nodes via the REST API
   Scenario: List nodes when none have been created
     Given a 'registration' named 'bobo' exists
       And there are no nodes 
-     When I authenticate as 'bobo'
-      And I 'GET' the path '/nodes' 
-     Then the inflated response should be an empty array
+     When I 'GET' the path '/nodes' 
+     Then the inflated response should be an empty hash 
 
   Scenario: List nodes when one has been created
     Given a 'registration' named 'bobo' exists
     Given a 'node' named 'webserver' exists
-     When I authenticate as 'bobo'
-      And I 'GET' the path '/nodes'
-     Then the inflated response should include '^http://.+/nodes/webserver$'
-
+     When I 'GET' the path '/nodes'
+     Then the inflated responses key 'webserver' should match '^http://.+/nodes/webserver$'
+  
   Scenario: List nodes when two have been created
     Given a 'registration' named 'bobo' exists
       And a 'node' named 'webserver' exists
       And a 'node' named 'dbserver' exists
-     When I authenticate as 'bobo'
-      And I 'GET' the path '/nodes'
+     When I 'GET' the path '/nodes'
      Then the inflated response should be '2' items long
-      And the inflated response should include '^http://.+/nodes/webserver$'
-      And the inflated response should include '^http://.+/nodes/dbserver$'
+     Then the inflated responses key 'webserver' should match '^http://.+/nodes/webserver$'
+     Then the inflated responses key 'dbserver' should match '^http://.+/nodes/dbserver$'
 
-  Scenario: List nodes when you are not authenticated 
-     When I 'GET' the path '/nodes' 
+  Scenario: List nodes none have been created with a wrong private key
+    Given a 'registration' named 'bobo' exists
+      And there are no cookbooks
+     When I 'GET' the path '/nodes' using a wrong private key
      Then I should get a '401 &quot;Unauthorized&quot;' exception
-</diff>
      <filename>features/api/nodes/list_nodes_api.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-@api @nodes @nodes_show
+@api @api_nodes @nodes_show
 Feature: Show a node via the REST API 
   In order to know what the details are for a node 
   As a Developer
@@ -7,19 +7,18 @@ Feature: Show a node via the REST API
   Scenario: Show a node
     Given a 'registration' named 'bobo' exists
       And a 'node' named 'webserver' exists
-     When I authenticate as 'bobo'
-      And I 'GET' the path '/nodes/webserver'
+     When I 'GET' the path '/nodes/webserver'
      Then the inflated response should respond to 'name' with 'webserver'
 
   Scenario: Show a missing node
     Given a 'registration' named 'bobo' exists
       And there are no nodes 
-     When I authenticate as 'bobo'
-      And I 'GET' the path '/nodes/bobo'
+     When I 'GET' the path '/nodes/bobo'
      Then I should get a '404 &quot;Not Found&quot;' exception
 
-  Scenario: Show a node without authenticating
-    Given a 'node' named 'webserver' exists
-      And I 'GET' the path '/nodes/webserver'
+  Scenario: Show a node with a wrong private key
+    Given a 'registration' named 'bobo' exists
+      And a 'node' named 'webserver' exists
+     When I 'GET' the path '/nodes/webserver' using a wrong private key
      Then I should get a '401 &quot;Unauthorized&quot;' exception
 </diff>
      <filename>features/api/nodes/show_node_api.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-@api @nodes @nodes_update
+@api @api_nodes @nodes_update
 Feature: Update a node
   In order to keep my node data up-to-date
   As a Developer
@@ -8,7 +8,6 @@ Feature: Update a node
     Given a 'registration' named 'bobo' exists
       And a 'node' named 'webserver' exists
       And sending the method '&lt;method&gt;' to the 'node' with '&lt;updated_value&gt;'
-     When I authenticate as 'bobo'
      When I 'PUT' the 'node' to the path '/nodes/webserver' 
      Then the inflated response should respond to '&lt;method&gt;' with '&lt;updated_value&gt;' 
      When I 'GET' the path '/nodes/webserver'
@@ -19,9 +18,18 @@ Feature: Update a node
       | run_list     | [ &quot;recipe[one]&quot;, &quot;recipe[two]&quot; ] |
       | snakes       | really arent so bad | 
       
-  Scenario: Update a node without authenticating
-    Given a 'node' named 'webserver'
-      And sending the method 'snakes' to the 'node' with 'night train'
-     When I 'PUT' the 'node' to the path '/nodes/webserver' 
+
+  Scenario: Update a node with a wrong private key
+    Given a 'registration' named 'bobo' exists
+      And a 'node' named 'webserver' exists
+      And sending the method 'run_list' to the 'node' with '[ &quot;recipe[one]&quot;, &quot;recipe[two]&quot; ]'
+     When I 'PUT' the 'node' to the path '/nodes/webserver' using a wrong private key
+     Then I should get a '401 &quot;Unauthorized&quot;' exception
+
+  Scenario: Update a node when I am not an admin
+    Given a 'registration' named 'not_admin' exists
+      And a 'node' named 'webserver' exists
+      And sending the method 'run_list' to the 'node' with '[ &quot;recipe[one]&quot;, &quot;recipe[two]&quot; ]'
+     When I 'PUT' the 'node' to the path '/nodes/webserver'
      Then I should get a '401 &quot;Unauthorized&quot;' exception
 </diff>
      <filename>features/api/nodes/update_node_api.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-@api @roles @roles_create
+@api @api_roles @roles_create
 Feature: Create a role via the REST API
   In order to create roles programatically 
   As a Devleoper
@@ -7,20 +7,25 @@ Feature: Create a role via the REST API
   Scenario: Create a new role 
     Given a 'registration' named 'bobo' exists
       And a 'role' named 'webserver'
-     When I authenticate as 'bobo'
-      And I 'POST' the 'role' to the path '/roles' 
+     When I 'POST' the 'role' to the path '/roles' 
       And the inflated responses key 'uri' should match '^http://.+/roles/webserver$'
 
   Scenario: Create a role that already exists
     Given a 'registration' named 'bobo' exists
       And an 'role' named 'webserver'
-     When I authenticate as 'bobo'
-      And I 'POST' the 'role' to the path '/roles' 
+     When I 'POST' the 'role' to the path '/roles' 
       And I 'POST' the 'role' to the path '/roles' 
      Then I should get a '403 &quot;Forbidden&quot;' exception
 
-  Scenario: Create a new role without authenticating
-    Given a 'role' named 'webserver'
+  Scenario: Create a new role with a wrong private key
+    Given a 'registration' named 'bobo' exists
+      And a 'role' named 'webserver'
+     When I 'POST' the 'role' to the path '/roles' using a wrong private key
+     Then I should get a '401 &quot;Unauthorized&quot;' exception
+
+  Scenario: Create a new role as a non-admin
+    Given a 'registration' named 'not_admin' exists
+      And a 'role' named 'webserver'
      When I 'POST' the 'role' to the path '/roles' 
      Then I should get a '401 &quot;Unauthorized&quot;' exception
 </diff>
      <filename>features/api/roles/create_role_api.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-@api @roles @roles_delete
+@api @api_roles @roles_delete
 Feature: Delete a Role via the REST API 
   In order to remove a role 
   As a Developer 
@@ -7,19 +7,24 @@ Feature: Delete a Role via the REST API
   Scenario: Delete a Role 
     Given a 'registration' named 'bobo' exists
       And a 'role' named 'webserver' exists
-     When I authenticate as 'bobo'
-      And I 'DELETE' the path '/roles/webserver'
+     When I 'DELETE' the path '/roles/webserver'
      Then the inflated response should respond to 'name' with 'webserver' 
 
   Scenario: Delete a Role that does not exist
     Given a 'registration' named 'bobo' exists
       And there are no roles 
-     When I authenticate as 'bobo'
      When I 'DELETE' the path '/roles/webserver'
      Then I should get a '404 &quot;Not Found&quot;' exception
+    
+  Scenario: Delete a Role with a wrong private key
+    Given a 'registration' named 'bobo' exists
+      And a 'role' named 'webserver' exists
+     When I 'DELETE' the path '/roles/webserver' using a wrong private key
+     Then I should get a '401 &quot;Unauthorized&quot;' exception
 
-  Scenario: Delete a Role without authenticating 
-    Given a 'role' named 'webserver'
+  Scenario: Delete a Role as a non-admin
+    Given a 'registration' named 'not_admin' exists
+      And a 'role' named 'webserver' exists
      When I 'DELETE' the path '/roles/webserver'
      Then I should get a '401 &quot;Unauthorized&quot;' exception
 </diff>
      <filename>features/api/roles/delete_role_api.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-@api @roles @roles_list
+@api @api_roles @roles_list
 Feature: List roles via the REST API
   In order to know what roles exists programatically
   As a Developer
@@ -6,30 +6,29 @@ Feature: List roles via the REST API
 
   Scenario: List roles when none have been created
     Given a 'registration' named 'bobo' exists
-      And there are no roles
-     When I authenticate as 'bobo'
-      And I 'GET' the path '/roles' 
-     Then the inflated response should be an empty array
+      And there are no roles 
+     When I 'GET' the path '/roles' 
+     Then the inflated response should be '1' items long 
 
   Scenario: List roles when one has been created
     Given a 'registration' named 'bobo' exists
     Given a 'role' named 'webserver' exists
-     When I authenticate as 'bobo'
-      And I 'GET' the path '/roles'
-     Then the inflated response should include '^http://.+/roles/webserver$'
+     When I 'GET' the path '/roles'
+     Then the inflated responses key 'webserver' should match '^http://.+/roles/webserver$'
 
   Scenario: List roles when two have been created
     Given a 'registration' named 'bobo' exists
       And a 'role' named 'webserver' exists
       And a 'role' named 'db' exists
-     When I authenticate as 'bobo'
-      And I 'GET' the path '/roles'
+     When I 'GET' the path '/roles'
      Then the inflated response should be '3' items long
-      And the inflated response should include '^http://.+/roles/role_test$'
-      And the inflated response should include '^http://.+/roles/webserver$'
-      And the inflated response should include '^http://.+/roles/db$'
+      And the inflated responses key 'role_test' should match '^http://.+/roles/role_test$'
+      And the inflated responses key 'webserver' should match '^http://.+/roles/webserver$'
+      And the inflated responses key 'db' should match '^http://.+/roles/db$'
 
-  Scenario: List roles when you are not authenticated 
-     When I 'GET' the path '/roles' 
+  Scenario: List roles when none have been created with a wrong private key
+    Given a 'registration' named 'bobo' exists
+      And there are no roles 
+     When I 'GET' the path '/roles' using a wrong private key
      Then I should get a '401 &quot;Unauthorized&quot;' exception
 </diff>
      <filename>features/api/roles/list_roles_api.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-@api @roles @roles_show
+@api @api_roles @roles_show
 Feature: Show a role via the REST API 
   In order to know what the details are for a Role 
   As a Developer
@@ -7,20 +7,18 @@ Feature: Show a role via the REST API
   Scenario: Show a role
     Given a 'registration' named 'bobo' exists
       And a 'role' named 'webserver' exists
-     When I authenticate as 'bobo'
-      And I 'GET' the path '/roles/webserver'
+     When I 'GET' the path '/roles/webserver'
      Then the inflated response should respond to 'name' with 'webserver'
 
   Scenario: Show a missing role
     Given a 'registration' named 'bobo' exists
       And there are no roles 
-     When I authenticate as 'bobo'
-      And I 'GET' the path '/roles/bobo'
+     When I 'GET' the path '/roles/bobo'
      Then I should get a '404 &quot;Not Found&quot;' exception
 
-  Scenario: Show a role without authenticating
-    Given a 'role' named 'webserver' exists
-      And I 'GET' the path '/roles/webserver'
+  Scenario: Show a role with a wrong private key
+    Given a 'registration' named 'bobo' exists
+      And a 'role' named 'webserver' exists
+     When I 'GET' the path '/roles/webserver' using a wrong private key
      Then I should get a '401 &quot;Unauthorized&quot;' exception
 
-</diff>
      <filename>features/api/roles/show_roles_api.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-@api @roles @roles_update
+@api @api_roles @roles_update
 Feature: Update a role
   In order to keep my role data up-to-date
   As a Developer
@@ -8,7 +8,6 @@ Feature: Update a role
     Given a 'registration' named 'bobo' exists
       And a 'role' named 'webserver' exists
       And sending the method '&lt;method&gt;' to the 'role' with '&lt;updated_value&gt;'
-     When I authenticate as 'bobo'
      When I 'PUT' the 'role' to the path '/roles/webserver' 
      Then the inflated response should respond to '&lt;method&gt;' with '&lt;updated_value&gt;' 
      When I 'GET' the path '/roles/webserver'
@@ -21,9 +20,17 @@ Feature: Update a role
       | default_attributes | { &quot;a&quot;: &quot;d&quot; } |
       | override_attributes | { &quot;c&quot;: &quot;e&quot; } |
       
-  Scenario: Update a role without authenticating
-    Given a 'role' named 'webserver'
-      And sending the method 'description' to the 'role' with 'Is easy'
-     When I 'PUT' the 'role' to the path '/roles/webserver' 
+  Scenario: Update a role with a wrong private key
+    Given a 'registration' named 'bobo' exists
+      And a 'role' named 'webserver' exists
+      And sending the method 'description' to the 'role' with 'gorilla'
+     When I 'PUT' the 'role' to the path '/roles/webserver' using a wrong private key
+     Then I should get a '401 &quot;Unauthorized&quot;' exception
+
+  Scenario: Update a role as a non-admin user 
+    Given a 'registration' named 'not_admin' exists
+      And a 'role' named 'webserver' exists
+      And sending the method 'description' to the 'role' with 'gorilla'
+     When I 'PUT' the 'role' to the path '/roles/webserver' using a wrong private key
      Then I should get a '401 &quot;Unauthorized&quot;' exception
 </diff>
      <filename>features/api/roles/update_roles_api.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-@client
+@client @client_run_interval
 Feature: Run chef-client at periodic intervals 
   In order to ensure a system is always correctly configured 
   As an Administrator</diff>
      <filename>features/chef-client/run_interval.feature</filename>
    </modified>
    <modified>
      <diff>@@ -6,9 +6,15 @@ log_location     STDOUT
 file_cache_path  File.join(tmpdir, &quot;cache&quot;)
 ssl_verify_mode  :verify_none
 registration_url &quot;http://127.0.0.1:4000&quot;
-openid_url       &quot;http://127.0.0.1:4001&quot;
+openid_url       &quot;http://127.0.0.1:4000&quot;
 template_url     &quot;http://127.0.0.1:4000&quot;
 remotefile_url   &quot;http://127.0.0.1:4000&quot;
 search_url       &quot;http://127.0.0.1:4000&quot;
-role_url          &quot;http://127.0.0.1:4000&quot;
-couchdb_database   'chef_integration'
+role_url         &quot;http://127.0.0.1:4000&quot;
+client_url       &quot;http://127.0.0.1:4000&quot;
+chef_server_url  &quot;http://127.0.0.1:4000&quot;
+validation_client_name &quot;validator&quot;
+systmpdir = File.expand_path(File.join(Dir.tmpdir, &quot;chef_integration&quot;))
+validation_key   File.join(systmpdir, &quot;validation.pem&quot;)
+client_key       File.join(systmpdir, &quot;client.pem&quot;)
+</diff>
      <filename>features/data/config/client.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,17 +6,33 @@ log_location       STDOUT
 file_cache_path    File.join(tmpdir, &quot;cache&quot;)
 ssl_verify_mode    :verify_none
 registration_url   &quot;http://127.0.0.1:4000&quot;
-openid_url         &quot;http://127.0.0.1:4001&quot;
+openid_url         &quot;http://127.0.0.1:4000&quot;
 template_url       &quot;http://127.0.0.1:4000&quot;
 remotefile_url     &quot;http://127.0.0.1:4000&quot;
 search_url         &quot;http://127.0.0.1:4000&quot;
-role_url          &quot;http://127.0.0.1:4000&quot;
+role_url           &quot;http://127.0.0.1:4000&quot;
+chef_server_url    &quot;http://127.0.0.1:4000&quot;
+client_url         &quot;http://127.0.0.1:4000&quot;
 cookbook_path      File.join(supportdir, &quot;cookbooks&quot;)
 openid_store_path  File.join(tmpdir, &quot;openid&quot;, &quot;store&quot;)
 openid_cstore_path File.join(tmpdir, &quot;openid&quot;, &quot;cstore&quot;)
 search_index_path  File.join(tmpdir, &quot;search_index&quot;)
 role_path          File.join(supportdir, &quot;roles&quot;)
-validation_token   'ceelo'
+signing_ca_path    File.join(tmpdir, &quot;ca&quot;)
 couchdb_database   'chef_integration'
 
+systmpdir = File.expand_path(File.join(Dir.tmpdir, &quot;chef_integration&quot;))
+
+validation_client_name &quot;validator&quot;
+validation_key   File.join(systmpdir, &quot;validation.pem&quot;)
+client_key       File.join(systmpdir, &quot;client.pem&quot;)
+web_ui_client_name &quot;chef-webui&quot;
+web_ui_key File.join(systmpdir, &quot;webui.pem&quot;)
+
+solr_jetty_path File.join(supportdir, &quot;solr&quot;, &quot;jetty&quot;)
+solr_heap_size &quot;250M&quot;
+solr_data_path File.join(supportdir, &quot;solr&quot;, &quot;data&quot;)
+solr_home_path File.join(supportdir, &quot;solr&quot;, &quot;home&quot;)
+solr_heap_size &quot;256M&quot;
+
 Chef::Log::Formatter.show_time = true</diff>
      <filename>features/data/config/server.rb</filename>
    </modified>
    <modified>
      <diff>@@ -19,7 +19,7 @@
 
 directory node[:int][:tmpdir] do
   owner &quot;root&quot;
-  mode 1777
+  mode &quot;1777&quot;
   action :create
 end
 </diff>
      <filename>features/data/cookbooks/integration_setup/recipes/default.rb</filename>
    </modified>
    <modified>
      <diff>@@ -17,11 +17,12 @@
 # limitations under the License.
 #
 
-node.save
-sleep 5
-search(:node, &quot;*&quot;) do |entry|
-  Chef::Log.error(entry.inspect)
-  entry[&quot;search_files&quot;].each do |filename|
-    file &quot;#{node[:tmpdir]}/#{filename}&quot; 
-  end
+# We have to sleep at least 10 seconds to confirm that the data has made it 
+# into the index.  We can only rely on this because we are in a test environment
+# in real-land Chef, the index is only eventually consistent.. and may take a
+# variable amount of time.
+sleep 10
+search(:users, &quot;*:*&quot;) do |entry|
+  file &quot;#{node[:tmpdir]}/#{entry[&quot;id&quot;]}&quot;
 end
+</diff>
      <filename>features/data/cookbooks/search/recipes/search_data.rb</filename>
    </modified>
    <modified>
      <diff>@@ -14,4 +14,4 @@
     &quot;ossining&quot;: &quot;whatever&quot;,
     &quot;snakes&quot;: &quot;on a plane&quot;
   }
-}
\ No newline at end of file
+}</diff>
      <filename>features/data/roles/role_test.json</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,4 @@
+@language
 Feature: Delayed Notifications
   In order to not impact the system we are configuring unduly
   As a developer</diff>
      <filename>features/language/delayed_notifications.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-@provider @git @deploy
+@provider @git @deploy @provider_deploy
 
 Feature: Deploy
   In order to repeatably and reliably deploy web apps from a source repository from the comfort of chef</diff>
      <filename>features/provider/deploy/deploy.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,4 @@
+@provider @provider_directory
 Feature: Create Directories 
   In order to save time
   As a Developer</diff>
      <filename>features/provider/directory/create_directories.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,4 @@
+@provider @provider_directory
 Feature: Delete Directories 
   In order to save time 
   As a Developer</diff>
      <filename>features/provider/directory/delete_directories.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,4 @@
+@provider @provider_execute
 Feature: Run Commands 
   In order to utilize the plethora of useful command line utilities 
   As a Developer</diff>
      <filename>features/provider/execute/run_commands.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,4 @@
+@provider @provider_file
 Feature: Manage Files
   In order to save time
   As a Developer</diff>
      <filename>features/provider/file/manage_files.feature</filename>
    </modified>
    <modified>
      <diff>@@ -4,11 +4,25 @@ Feature: Search Data
   As a Developer
   I want to search the data 
 
-  Scenario: Search the node index
+  Scenario: Search the user index
     Given a validated node
       And it includes the recipe 'search::search_data'
+      And a 'data_bag' named 'users' exists
+      And a 'data_bag_item' named 'francis' exists
+      And a 'data_bag_item' named 'axl_rose' exists
      When I run the chef-client
      Then the run should exit '0'
-      And a file named 'search_one.txt' should exist
-      And a file named 'search_two.txt' should exist
+      And a file named 'francis' should exist
+      And a file named 'axl_rose' should exist
+
+  Scenario: Search the user index without a block
+    Given a validated node
+      And it includes the recipe 'search::search_data_noblock'
+      And a 'data_bag' named 'users' exists
+      And a 'data_bag_item' named 'francis' exists
+      And a 'data_bag_item' named 'axl_rose' exists
+     When I run the chef-client
+     Then the run should exit '0'
+      And a file named 'francis' should exist
+      And a file named 'axl_rose' should exist
 </diff>
      <filename>features/search/search_data.feature</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,6 @@
 #
 # Author:: Adam Jacob (&lt;adam@opscode.com&gt;)
+# Author:: Chris Walters (&lt;cw@opscode.com&gt;)
 # Copyright:: Copyright (c) 2008 Opscode, Inc.
 # License:: Apache License, Version 2.0
 #
@@ -51,3 +52,4 @@ When /^I run the rake task to generate cookbook metadata$/ do
     end
   end
 end
+</diff>
      <filename>features/steps/cookbook_steps.rb</filename>
    </modified>
    <modified>
      <diff>@@ -54,6 +54,6 @@ end
 
 Then /^the second chef run should have skipped deployment$/ do
   expected_deploy = &quot;#{tmpdir}/deploy/releases/62c9979f6694612d9659259f8a68d71048ae9a5b&quot;
-  Then &quot;'stdout' should have 'INFO: Already deployed app at #{expected_deploy}, skipping. Use action :force_deploy to force.'&quot;
+  Then &quot;'stdout' should not have 'INFO: Already deployed app at #{expected_deploy}.  Rolling back to it - use action :force_deploy to re-checkout this revision.'&quot;
 end
   </diff>
      <filename>features/steps/deploy_steps.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,14 +1,74 @@
 
+require 'ostruct'
+
 Before do
   @fixtures = {
+    'client' =&gt; {
+      'isis' =&gt; Proc.new do
+        c = Chef::ApiClient.new
+        c.name &quot;isis&quot;
+        c.create_keys
+        c
+      end,
+      'isis_update' =&gt; {
+        'name' =&gt; 'isis',
+        'private_key' =&gt; true
+      },
+      'neurosis' =&gt; Proc.new do
+        c = Chef::ApiClient.new
+        c.name &quot;neurosis&quot;
+        c.create_keys
+        c
+      end,
+      'adminmonkey' =&gt; Proc.new do
+        c = Chef::ApiClient.new
+        c.name &quot;adminmonkey&quot;
+        c.admin true
+        c.create_keys
+        c
+      end
+    },
+    'signing_caller' =&gt;{ 
+      :user_id=&gt;'bobo', :secret_key =&gt; &quot;/tmp/poop.pem&quot;
+    },
     'registration' =&gt; { 
       'bobo' =&gt; Proc.new do
-        r = Chef::OpenIDRegistration.new
-        r.name = &quot;bobo&quot;
-        r.set_password('tclown')
-        r.validated = true
-        r.admin = true
-        r
+        OpenStruct.new({ :save =&gt; true })
+      end,
+      'not_admin' =&gt; Proc.new do
+        OpenStruct.new({ :save =&gt; true })
+      end
+    },
+    'data_bag' =&gt; {
+      'users' =&gt; Proc.new do
+        b = Chef::DataBag.new
+        b.name &quot;users&quot;
+        b
+      end,
+      'rubies' =&gt; Proc.new do
+        b = Chef::DataBag.new
+        b.name &quot;rubies&quot;
+        b
+      end
+    },
+    'data_bag_item' =&gt; {
+      'francis' =&gt; Proc.new do
+        i = Chef::DataBagItem.new
+        i.data_bag &quot;users&quot;
+        i.raw_data = { &quot;id&quot; =&gt; &quot;francis&quot; }
+        i
+      end,
+      'francis_extra' =&gt; Proc.new do
+        i = Chef::DataBagItem.new
+        i.data_bag &quot;users&quot;
+        i.raw_data = { &quot;id&quot; =&gt; &quot;francis&quot;, &quot;extra&quot; =&gt; &quot;majority&quot; }
+        i
+      end,
+      'axl_rose' =&gt; Proc.new do
+        i = Chef::DataBagItem.new
+        i.data_bag &quot;users&quot;
+        i.raw_data = { &quot;id&quot; =&gt; &quot;axl_rose&quot; }
+        i
       end
     },
     'role' =&gt; {
@@ -46,12 +106,29 @@ Before do
         n.run_list &lt;&lt; &quot;oracle&quot;
         n.just &quot;kidding - who uses oracle?&quot;
         n
+      end,
+      'sync' =&gt; Proc.new do
+        n = Chef::Node.new
+        n.name 'sync'
+        n.run_list &lt;&lt; &quot;node_cookbook_sync&quot;
+        n
       end
     }
   }
   @stash = {}
 end
 
+def sign_request(http_method, private_key, user_id, body = &quot;&quot;)
+  timestamp = Time.now.utc.iso8601
+  sign_obj = Mixlib::Auth::SignedHeaderAuth.signing_object(
+                                                     :http_method=&gt;http_method,
+                                                     :body=&gt;body,
+                                                     :user_id=&gt;user_id,
+                                                     :timestamp=&gt;timestamp)
+  signed =  sign_obj.sign(private_key).merge({:host =&gt; &quot;localhost&quot;})
+  signed.inject({}){|memo, kv| memo[&quot;#{kv[0].to_s.upcase}&quot;] = kv[1];memo}
+end
+
 def get_fixture(stash_name, stash_key)
   fixy = @fixtures[stash_name][stash_key]
   if fixy.kind_of?(Proc)
@@ -62,20 +139,48 @@ def get_fixture(stash_name, stash_key)
 end
 
 Given /^an? '(.+)' named '(.+)'$/ do |stash_name, stash_key|
-  @stash[stash_name] = get_fixture(stash_name, stash_key)
+  # BUGBUG: I need to reference fixtures individually, but the fixtures, as written, store under the type, not the fixture's identifier and I don't currently have time to re-write the tests
+
+  key = case stash_name
+        when 'file','hash'
+          stash_key
+        else
+          stash_name
+        end
+  @stash[key] = get_fixture(stash_name, stash_key)
 end
 
-Given /^an? '(.+)' named '(.+)' exists$/ do |stash_name, stash_key|
+Given /^an? '(.+)' named '(.+)' exists$/ do |stash_name, stash_key|  
   @stash[stash_name] = get_fixture(stash_name, stash_key) 
-  if @stash[stash_name].respond_to?(:save)
-    @stash[stash_name].save
-  else
-    request(&quot;/#{stash_name.pluralize}&quot;, { 
-      :method =&gt; &quot;POST&quot;, 
-      &quot;HTTP_ACCEPT&quot; =&gt; 'application/json',
-      &quot;CONTENT_TYPE&quot; =&gt; 'application/json',
-      :input =&gt; @stash[stash_name].to_json 
-    })
+    
+  if stash_name == 'registration'
+    if stash_key == &quot;bobo&quot;
+      r = Chef::REST.new(Chef::Config[:registration_url], Chef::Config[:validation_client_name], Chef::Config[:validation_key])
+      r.register(&quot;bobo&quot;, &quot;#{tmpdir}/bobo.pem&quot;)
+      c = Chef::ApiClient.cdb_load(&quot;bobo&quot;)
+      c.admin(true)
+      c.cdb_save
+      @rest = Chef::REST.new(Chef::Config[:registration_url], 'bobo', &quot;#{tmpdir}/bobo.pem&quot;)
+    elsif stash_key == &quot;not_admin&quot;
+      r = Chef::REST.new(Chef::Config[:registration_url], Chef::Config[:validation_client_name], Chef::Config[:validation_key])
+      r.register(&quot;not_admin&quot;, &quot;#{tmpdir}/not_admin.pem&quot;)
+      c = Chef::ApiClient.cdb_load(&quot;not_admin&quot;)
+      c.cdb_save
+      @rest = Chef::REST.new(Chef::Config[:registration_url], 'not_admin', &quot;#{tmpdir}/not_admin.pem&quot;)
+    end
+  else 
+    if @stash[stash_name].respond_to?(:cdb_save)
+      @stash[stash_name].cdb_save
+    elsif @stash[stash_name].respond_to?(:save)#stash_name == &quot;registration&quot; 
+      @stash[stash_name].save
+    else
+      request(&quot;#{stash_name.pluralize}&quot;, { 
+        :method =&gt; &quot;POST&quot;, 
+        &quot;HTTP_ACCEPT&quot; =&gt; 'application/json',
+        &quot;CONTENT_TYPE&quot; =&gt; 'application/json',
+        :input =&gt; @stash[stash_name].to_json 
+      }.merge(sign_request(&quot;POST&quot;, OpenSSL::PKey::RSA.new(IO.read(&quot;#{tmpdir}/client.pem&quot;)), &quot;bobo&quot;)))
+    end
   end
 end
 
@@ -93,8 +198,8 @@ Given /^removing the '(.+)' field '(.+)'$/ do |stash_name, key|
 end
 
 Given /^there are no (.+)$/ do |stash_name|
-  case stash_name
-  when 'roles'
-    Chef::Role.list(true).each { |r| r.destroy }
-  end
+end
+
+Given /^I wait for '(\d+)' seconds$/ do |time|
+  sleep time.to_i
 end</diff>
      <filename>features/steps/fixture_steps.rb</filename>
    </modified>
    <modified>
      <diff>@@ -20,9 +20,8 @@
 # Given
 ###
 Given /^a validated node$/ do
-  client.validation_token = Chef::Config[:validation_token] = 'ceelo'
+  client.determine_node_name
   client.register
-  client.authenticate
   client.build_node
   client.node.recipes &lt;&lt; &quot;integration_setup&quot;
 end</diff>
      <filename>features/steps/node_steps.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,21 +1,55 @@
-When /^I '(.+)' the path '(.+)'$/ do |http_method, request_uri|
+When /^I '([^']*)' (?:to )?the path '([^']*)'$/ do |http_method, request_uri|
   begin
     self.response = rest.send(&quot;#{http_method}_rest&quot;.downcase.to_sym, request_uri)
-    self.inflated_response = self.response 
+    self.inflated_response = self.response
   rescue
+    Chef::Log.debug(&quot;Caught exception in request: #{$!.message}&quot;)
     self.exception = $!
   end
 end
 
+When /^I '([^']*)' to the path '(.+)'$/ do |http_method, request_uri|
+  When &quot;I '#{http_method}' the path '#{request_uri}'&quot;
+end
+
+When /^I '(.+)' the path '(.+)' using a wrong private key$/ do |http_method, request_uri|
+  key = OpenSSL::PKey::RSA.generate(2048)
+  File.open(File.join(tmpdir, 'false_key.pem'), &quot;w&quot;) { |f| f.print key }
+  @rest = Chef::REST.new(Chef::Config[:chef_server_url], 'snakebite' , File.join(tmpdir, 'false_key.pem'))
+
+  When &quot;I '#{http_method}' the path '#{request_uri}'&quot;
+end
+
 When /^I '(.+)' the '(.+)' to the path '(.+)'$/ do |http_method, stash_key, request_uri|
   begin
-    self.response = rest.send(&quot;#{http_method}_rest&quot;.downcase.to_sym, request_uri, stash[stash_key])
+    self.response = rest.send(&quot;#{http_method.to_s.downcase}_rest&quot;.downcase.to_sym, request_uri, stash[stash_key])
     self.inflated_response = response
   rescue
     self.exception = $!
   end
 end
 
+When /^I '(.+)' the '(.+)' to the path '(.+)' using a wrong private key$/ do |http_method, stash_key, request_uri|
+  key = OpenSSL::PKey::RSA.generate(2048)
+  File.open(File.join(tmpdir, 'false_key.pem'), &quot;w&quot;) { |f| f.print key }
+  @rest = Chef::REST.new(Chef::Config[:chef_server_url], 'snakebite' , File.join(tmpdir, 'false_key.pem'))
+
+  When &quot;I '#{http_method}' the '#{stash_key}' to the path '#{request_uri}'&quot;
+end
+
+When /^I delete local private key/ do
+  Chef::FileCache.delete(&quot;private_key.pem&quot;)
+end
+
+When /^I register '(.+)'$/ do |user|
+  begin
+    rest = Chef::REST.new(Chef::Config[:registration_url])
+    rest.register(&quot;bobo&quot;)
+  rescue
+    self.exception = $!
+  end
+end
+
 When /^I authenticate as '(.+)'$/ do |reg|
   begin
     rest.authenticate(reg, 'tclown')
@@ -24,3 +58,59 @@ When /^I authenticate as '(.+)'$/ do |reg|
   end
 end
 
+
+
+
+# When /^I '(.+)' the path '(.+)'$/ do |http_method, request_uri|
+#   begin
+#     #if http_method.downcase == 'get'
+#     #  self.response = @rest.get_rest(request_uri)
+#     #else
+#       #puts &quot;test test test \n\n\n\n\n\n\n&quot;
+#       @response = @rest.send(&quot;#{http_method}_rest&quot;.downcase.to_sym, request_uri)
+#     #end
+#     puts &quot;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&quot;
+#     puts @response
+#     puts @response['content-type']
+#     #puts self.response
+#     #puts self.response.inspect
+#     #self.inflated_response = self.response
+#     @inflated_response = @response#JSON.parse(response.body.to_s) 
+#     puts &quot;~~~~~~~~INFLATED RESPONSE~~~~~~~~~~~~&quot;
+#     puts @inflated_response
+#   rescue
+#     self.exception = $!
+#   end
+# end
+# 
+# When /^I '(.+)' the '(.+)' to the path '(.+)'$/ do |http_method, stash_key, request_uri|
+#   begin
+#     #if http_method.downcase == 'post'
+#     #  puts &quot;post request&quot;
+#     #  self.response = @rest.post_rest(request_uri, @stash[stash_key])
+#     #  puts self.response
+#     #else
+#     puts &quot;This is the request -- @stash[stash_key]:&quot; 
+#     puts @stash[stash_key].to_s
+#     @response = @rest.send(&quot;#{http_method}_rest&quot;.downcase.to_sym, request_uri, @stash[stash_key])
+#     #end
+#     puts &quot;This is the response:&quot;
+#     #puts self.response.body.to_s
+#     puts @response
+#     #self.inflated_response = response
+#     @inflated_response = @response#JSON.parse(self.response.body.to_s)
+#     puts &quot;~~~~~~~~INFLATED RESPONSE~~~~~~~~~~~~&quot;
+#     puts @inflated_response
+#   rescue
+#     self.exception = $!
+#   end
+# end
+# 
+# When /^I authenticate as '(.+)'$/ do |reg|
+#   begin
+#     rest.authenticate(reg, 'tclown')
+#   rescue
+#     self.exception = $!
+#   end
+# end
+# </diff>
      <filename>features/steps/request_steps.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,70 +3,129 @@ Then /^I should get a '(.+)' exception$/ do |exception|
 end
 
 Then /^the response code should be '(.+)'$/ do |response_code|
-  response.status.should == response_code.to_i
+  self.response.status.should == response_code.to_i
+end
+
+Then /^the inflated responses key '(.+)' should be the integer '(\d+)'$/ do |key, int|
+  inflated_response[key].should == int.to_i
 end
 
 Then /^the inflated responses key '(.+)' should match '(.+)'$/ do |key, regex|
-  inflated_response[key].should =~ /#{regex}/
+  puts self.inflated_response.inspect if ENV['DEBUG']
+  self.inflated_response[key].should =~ /#{regex}/m  
+end
+
+Then /^the inflated responses key '(.+)' should be literally '(.+)'$/ do |key, literal|
+  puts self.inflated_response.inspect if ENV['DEBUG']
+  to_check = case literal
+             when &quot;true&quot;
+               true
+             when &quot;false&quot;
+               false
+             end
+
+  self.inflated_response[key].should == to_check 
+end
+
+Then /^the inflated response should match '(.+)' as json$/ do |regex|
+  puts self.inflated_response.inspect if ENV[&quot;DEBUG&quot;]
+  self.inflated_response.to_json.should =~ /#{regex}/m
+end
+
+Then /^the inflated responses key '(.+)' should match '(.+)' as json$/ do |key, regex|
+  puts self.inflated_response.inspect if ENV[&quot;DEBUG&quot;]
+  self.inflated_response[key].to_json.should =~ /#{regex}/m
+end
+
+Then /^the inflated responses key '(.+)' item '(\d+)' should be a kind of '(.+)'$/ do |key, index, constant|
+  inflated_response[key][index.to_i].should be_a_kind_of(eval(constant))
+end
+
+Then /^the inflated responses key '(.+)' item '(\d+)' key '(.+)' should be '(.+)'$/ do |key, index, sub_key, to_equal|
+  inflated_response[key][index.to_i][sub_key].should == to_equal
+end
+
+Then /^the inflated responses key '(.+)' should be '(\d+)' items long$/ do |key, length| 
+  inflated_response[key].length.should == length.to_i
 end
 
 Then /^the inflated responses key '(.+)' should not exist$/ do |key|
-  inflated_response.has_key?(key).should == false
+  self.inflated_response.has_key?(key).should == false
 end
 
 Then /^the inflated responses key '(.+)' should exist$/ do |key|
-  inflated_response.has_key?(key).should == true 
+  self.inflated_response.has_key?(key).should == true 
 end
 
 Then /^the inflated response should be an empty array$/ do
-  inflated_response.should == []
+  self.inflated_response.should == []
+end
+
+Then /^the inflated response should be an empty hash$/ do
+  self.inflated_response.should == {} 
 end
 
 Then /^the inflated response should include '(.+)'$/ do |entry|
-  inflated_response.detect { |n| n =~ /#{entry}/ }.should be(true)
+  puts self.inflated_response.inspect
+  self.inflated_response.detect { |n| n =~ /#{entry}/ }.should be(true)
 end
 
 Then /^the inflated response should be '(.+)' items long$/ do |length|
-  inflated_response.length.should == length.to_i
+  if length.respond_to?(:keys)
+    self.inflated_response.keys.length.should == length.to_i
+  else
+    self.inflated_response.length.should == length.to_i
+  end
 end
 
 Then /^the '(.+)' header should match '(.+)'$/ do |header, regex|
-  response.headers[header].should =~ /#{regex}/
+  self.response.headers[header].should =~ /#{regex}/
 end
 
 Then /^the inflated responses key '(.+)' should include '(.+)'$/ do |key, regex|
-  inflated_response[key].detect { |n| n =~ /#{regex}/ }.should be(true)
+  self.inflated_response[key].detect { |n| n =~ /#{regex}/ }.should be(true)
 end
 
 Then /^the inflated response should match the '(.+)'$/ do |stash_name|
   stash[stash_name].each do |k,v|
-    inflated_response[k.to_s].should == v
+    self.inflated_response[k.to_s].should == v
   end
 end
 
 Then /^the inflated response should be the '(.+)'$/ do |stash_key|
-  stash[stash_key].should == inflated_response
+  stash[stash_key].should == self.inflated_response
 end
 
 Then /^the inflated response should be a kind of '(.+)'$/ do |thing|
-  inflated_response.should be_a_kind_of(thing)
+  self.inflated_response.should be_a_kind_of(thing)
 end
 
 Then /^the inflated response should respond to '(.+)' with '(.+)'$/ do |method, to_match|
   to_match = JSON.parse(to_match) if to_match =~ /^\[|\{/
-  inflated_response.send(method.to_sym).should == to_match 
+  to_match = true if to_match == 'true'
+  to_match = false if to_match == 'false'
+  self.inflated_response.send(method.to_sym).should == to_match 
 end
 
 Then /^the inflated response should respond to '(.+)' and match '(.+)'$/ do |method, to_match|
-  inflated_response.send(method.to_sym).should == to_match 
+  self.inflated_response.send(method.to_sym).should == to_match 
 end
 
 
 Then /^the fields in the inflated response should match the '(.+)'$/ do |stash_name|
-  inflated_response.each do |k,v|
+  self.inflated_response.each do |k,v|
     unless k =~ /^_/ || k == 'couchrest-type'
       stash[stash_name][k.to_sym].should == v
     end
   end
 end
 
+Then /^the data_bag named '(.+)' should not have an item named '(.+)'$/ do |data_bag, item|
+  exists = true
+  begin
+    Chef::DataBagItem.load(data_bag, item, @couchdb)
+  rescue
+    exists = false
+  end
+  exists.should == false
+end</diff>
      <filename>features/steps/response_steps.rb</filename>
    </modified>
    <modified>
      <diff>@@ -24,7 +24,7 @@ When /^I run the chef\-client$/ do
   @chef_args ||= &quot;&quot;
   @config_file ||= File.expand_path(File.join(File.dirname(__FILE__), '..', 'data', 'config', 'client.rb'))
   status = Chef::Mixin::Command.popen4(
-    &quot;chef-client -l #{@log_level} -c #{@config_file} #{@chef_args}&quot;) do |p, i, o, e|
+    &quot;#{File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;..&quot;, &quot;chef&quot;, &quot;bin&quot;, &quot;chef-client&quot;)} -l #{@log_level} -c #{@config_file} #{@chef_args}&quot;) do |p, i, o, e|
     @stdout = o.gets(nil)
     @stderr = e.gets(nil)
   end
@@ -46,17 +46,17 @@ When /^I run the chef\-client with '(.+)' for '(.+)' seconds$/ do |args, run_for
 end
 
 When /^I run the chef\-client for '(.+)' seconds$/ do |run_for|
-  cid = fork { 
+  cid = Process.fork { 
     sleep run_for.to_i
-    client_pid = `ps ax | grep chef-client | grep -v grep | grep -v rake | grep -v cucumber | awk '{ print $1 }'`
-    Process.kill(&quot;INT&quot;, client_pid.to_i)
+    Process.kill(&quot;INT&quot;, /^(.+chef\-client.+\-i.*)$/.match(`ps -ef`).to_s.split[1].to_i)
+    exit
   } 
   When 'I run the chef-client'
-  Process.waitpid2(cid)
+  Process.wait2(cid)
 end
 
 When /^I run the chef\-client at log level '(.+)'$/ do |log_level|
-  @log_level = log_level
+  @log_level = log_level.to_sym
   When &quot;I run the chef-client&quot;
 end
 
@@ -76,11 +76,17 @@ log_location     File.join(tmpdir, &quot;silly-monkey.log&quot;)
 file_cache_path  File.join(tmpdir, &quot;cache&quot;)
 ssl_verify_mode  :verify_none
 registration_url &quot;http://127.0.0.1:4000&quot;
-openid_url       &quot;http://127.0.0.1:4001&quot;
+openid_url       &quot;http://127.0.0.1:4000&quot;
 template_url     &quot;http://127.0.0.1:4000&quot;
 remotefile_url   &quot;http://127.0.0.1:4000&quot;
 search_url       &quot;http://127.0.0.1:4000&quot;
-couchdb_database   'chef_integration'
+role_url         &quot;http://127.0.0.1:4000&quot;
+client_url       &quot;http://127.0.0.1:4000&quot;
+chef_server_url  &quot;http://127.0.0.1:4000&quot;
+validation_client_name &quot;validator&quot;
+systmpdir = File.expand_path(File.join(Dir.tmpdir, &quot;chef_integration&quot;))
+validation_key   File.join(systmpdir, &quot;validation.pem&quot;)
+client_key       File.join(systmpdir, &quot;client.pem&quot;)
 CONFIG
   
   @config_file = File.expand_path(File.join(File.dirname(__FILE__), '..', 'data', 'config', 'client-with-logging.rb'))  
@@ -90,12 +96,11 @@ CONFIG
 
   self.cleanup_files &lt;&lt; @config_file
   
-  @status = Chef::Mixin::Command.popen4(&quot;chef-client -c #{@config_file}&quot;) do |p, i, o, e|
+  
+  @status = Chef::Mixin::Command.popen4(&quot;#{File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;..&quot;, &quot;chef&quot;, &quot;bin&quot;, &quot;chef-client&quot;)} -c #{@config_file} #{@chef_args}&quot;) do |p, i, o, e|
     @stdout = o.gets(nil)
     @stderr = e.gets(nil)
   end
-
-  
 end
 
 ###</diff>
      <filename>features/steps/run_client_steps.rb</filename>
    </modified>
    <modified>
      <diff>@@ -26,7 +26,7 @@ When /^I run chef-solo with the '(.+)' recipe$/ do |recipe_name|
   cleanup_files &lt;&lt; config_file
 
   binary_path = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'chef', 'bin', 'chef-solo'))
-  command = &quot;chef-solo -c #{config_file} -j #{dna_file}&quot;
+  command = &quot;#{binary_path} -c #{config_file} -j #{dna_file}&quot;
   command += &quot; -l debug&quot; if ENV['LOG_LEVEL'] == 'debug'
 
   # Run it</diff>
      <filename>features/steps/run_solo.rb</filename>
    </modified>
    <modified>
      <diff>@@ -36,4 +36,4 @@ end
 When /^I attach the file at &quot;(.*)&quot; to &quot;(.*)&quot; $/ do |path, field|
   attach_file(field, path)
 end
- 
\ No newline at end of file
+ </diff>
      <filename>features/steps/webrat_steps.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,3 @@
-#
-# Author:: Adam Jacob (&lt;adam@opscode.com&gt;)
 # Copyright:: Copyright (c) 2008 Opscode, Inc.
 # License:: Apache License, Version 2.0
 #
@@ -16,46 +14,126 @@
 # limitations under the License.
 #
 
-%w{chef chef-server chef-server-slice}.each do |inc_dir|
+%w{chef chef-server chef-server-slice chef-solr}.each do |inc_dir|
   $: &lt;&lt; File.join(File.dirname(__FILE__), '..', '..', inc_dir, 'lib')
 end
 
+Thread.abort_on_exception = true
+
 require 'rubygems'
 require 'spec'
 require 'chef'
 require 'chef/config'
 require 'chef/client'
+require 'chef/data_bag'
+require 'chef/data_bag_item'
+require 'chef/api_client'
+require 'chef/solr'
+require 'chef/certificate'
 require 'tmpdir'
 require 'merb-core'
 require 'merb_cucumber/world/webrat'
+require 'chef/streaming_cookbook_uploader'
 require 'webrick'
 
 def Spec.run? ; true; end
 
-Chef::Config.from_file(File.join(File.dirname(__FILE__), '..', 'data', 'config', 'server.rb'))
-Chef::Config[:log_level] = :error
-Ohai::Config[:log_level] = :error
+ENV['LOG_LEVEL'] ||= 'error'
+
+def setup_logging
+  Chef::Config.from_file(File.join(File.dirname(__FILE__), '..', 'data', 'config', 'server.rb'))
+  Merb.logger.auto_flush = true
+  if ENV['DEBUG'] == 'true' || ENV['LOG_LEVEL'] == 'debug'
+    Chef::Config[:log_level] = :debug
+    Chef::Log.level(:debug)
+    Merb.logger.set_log(STDOUT, :debug) 
+  else
+    Chef::Config[:log_level] = ENV['LOG_LEVEL'].to_sym 
+    Chef::Log.level(ENV['LOG_LEVEL'].to_sym)
+    Merb.logger.set_log(STDOUT, ENV['LOG_LEVEL'].to_sym)
+  end
+  Nanite::Log.logger = Ohai::Log.logger = Chef::Log.logger 
+end
+
+def setup_nanite
+  Chef::Config[:nanite_identity] = &quot;chef-integration-test&quot;
+  Chef::Nanite.in_event { Chef::Log.debug(&quot;Nanite is up!&quot;) } 
+  Chef::Log.debug(&quot;Waiting for Nanites to register with us as a mapper&quot;)
+  sleep 10
+end
 
-if ENV['DEBUG'] = 'true'
-  Merb.logger.set_log(STDOUT, :debug) if ENV['DEBUG'] = 'true'
-else
-  Merb.logger.set_log(STDOUT, :error)
+def delete_databases
+  c = Chef::REST.new(Chef::Config[:couchdb_url], nil, nil)
+  %w{chef_integration chef_integration_safe}.each do |db|
+    begin
+      c.delete_rest(&quot;#{db}/&quot;)
+    rescue
+    end
+  end
+end
+
+def create_databases
+  Chef::Log.info(&quot;Creating bootstrap databases&quot;)
+  cdb = Chef::CouchDB.new(Chef::Config[:couchdb_url], &quot;chef_integration&quot;)
+  cdb.create_db
+  cdb.create_id_map
+  Chef::Node.create_design_document
+  Chef::Role.create_design_document
+  Chef::DataBag.create_design_document
+  Chef::ApiClient.create_design_document
+  Chef::Role.sync_from_disk_to_couchdb
+  Chef::Certificate.generate_signing_ca
+  Chef::Certificate.gen_validation_key
+  Chef::Certificate.gen_validation_key(Chef::Config[:web_ui_client_name], Chef::Config[:web_ui_key])
+  system(&quot;cp #{File.join(Dir.tmpdir, &quot;chef_integration&quot;, &quot;validation.pem&quot;)} #{Dir.tmpdir}&quot;)
+  system(&quot;cp #{File.join(Dir.tmpdir, &quot;chef_integration&quot;, &quot;webui.pem&quot;)} #{Dir.tmpdir}&quot;)
+end
+
+def prepare_replicas
+  c = Chef::REST.new(Chef::Config[:couchdb_url], nil, nil)
+  c.put_rest(&quot;chef_integration_safe/&quot;, nil)
+  c.post_rest(&quot;_replicate&quot;, { &quot;source&quot; =&gt; &quot;#{Chef::Config[:couchdb_url]}/chef_integration&quot;, &quot;target&quot; =&gt; &quot;#{Chef::Config[:couchdb_url]}/chef_integration_safe&quot; })
+  c.delete_rest(&quot;chef_integration&quot;)
+end
+
+def cleanup
+  if File.exists?(Chef::Config[:validation_key])
+    File.unlink(Chef::Config[:validation_key])
+  end
+  if File.exists?(Chef::Config[:web_ui_key])
+    File.unlink(Chef::Config[:web_ui_key])
+  end
 end
 
 Merb.start_environment(
-  :merb_root =&gt; File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;..&quot;, &quot;chef-server&quot;), 
+  :merb_root =&gt; File.expand_path(File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;..&quot;, &quot;chef-server&quot;)), 
   :testing =&gt; true, 
   :adapter =&gt; 'runner',
   :environment =&gt; ENV['MERB_ENV'] || 'test',
   :session_store =&gt; 'memory'
 )
 
+###
+# Pre-testing setup
+###
+setup_logging
+setup_nanite
+cleanup
+delete_databases
+create_databases
+prepare_replicas
+
 Spec::Runner.configure do |config|
   config.include(Merb::Test::ViewHelper)
   config.include(Merb::Test::RouteHelper)
   config.include(Merb::Test::ControllerHelper)
 end
 
+Chef::Log.info(&quot;Ready to run tests&quot;)
+
+###
+# The Cucumber World
+###
 module ChefWorld
 
   attr_accessor :recipe, :cookbook, :response, :inflated_response, :log_level,
@@ -67,7 +145,7 @@ module ChefWorld
   end
 
   def rest
-    @rest ||= Chef::REST.new('http://localhost:4000')
+    @rest ||= Chef::REST.new('http://localhost:4000', nil, nil)
   end
 
   def tmpdir
@@ -104,7 +182,24 @@ end
 
 World(ChefWorld)
 
+Before do
+  system(&quot;mkdir -p #{tmpdir}&quot;)
+  system(&quot;cp -r #{File.join(Dir.tmpdir, &quot;validation.pem&quot;)} #{File.join(tmpdir, &quot;validation.pem&quot;)}&quot;)
+  system(&quot;cp -r #{File.join(Dir.tmpdir, &quot;webui.pem&quot;)} #{File.join(tmpdir, &quot;webui.pem&quot;)}&quot;)
+  Chef::CouchDB.new(Chef::Config[:couchdb_url], &quot;chef_integration&quot;).create_db
+  c = Chef::REST.new(Chef::Config[:couchdb_url], nil, nil)
+  c.post_rest(&quot;_replicate&quot;, { 
+    &quot;source&quot; =&gt; &quot;#{Chef::Config[:couchdb_url]}/chef_integration_safe&quot;,
+    &quot;target&quot; =&gt; &quot;#{Chef::Config[:couchdb_url]}/chef_integration&quot; 
+  })
+end
+
 After do
+  r = Chef::REST.new(Chef::Config[:couchdb_url], nil, nil)
+  r.delete_rest(&quot;chef_integration/&quot;)
+  s = Chef::Solr.new
+  s.solr_delete_by_query(&quot;*:*&quot;)
+  s.solr_commit
   gemserver.shutdown
   gemserver_thread &amp;&amp; gemserver_thread.join
   
@@ -120,5 +215,6 @@ After do
   end
   data_tmp = File.join(File.dirname(__FILE__), &quot;..&quot;, &quot;data&quot;, &quot;tmp&quot;)
   system(&quot;rm -rf #{data_tmp}/*&quot;)
+  system(&quot;rm -rf #{tmpdir}&quot;)
 end
 </diff>
      <filename>features/support/env.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>chef-server-slice/LICENSE</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/NOTICE</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/README.rdoc</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/Rakefile</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/application.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/cookbook_files.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/cookbook_segment.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/cookbook_templates.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/cookbooks.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/exceptions.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/main.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/nodes.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/openid_consumer.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/openid_register.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/openid_server.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/roles.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/search.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/search_entries.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/controllers/status.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/application_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/cookbook_attributes_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/cookbook_definitions_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/cookbook_files_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/cookbook_libraries_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/cookbook_recipes_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/cookbook_templates_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/cookbooks_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/exceptions_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/global_helpers.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/nodes_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/openid_consumer_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/openid_register_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/openid_server_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/openid_server_helpers.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/roles_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/search_entries_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/search_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/helpers/status_helper.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/cookbook_templates/index.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/cookbooks/index.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/cookbooks/show.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/exceptions/bad_request.json.erb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/exceptions/internal_server_error.html.erb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/exceptions/not_acceptable.html.erb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/exceptions/not_found.html.erb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/exceptions/standard_error.html.erb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/layout/chef_server_slice.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/layout/login.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/main/index.html.erb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/nodes/_action.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/nodes/_form.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/nodes/_navigation.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/nodes/_resource.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/nodes/edit.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/nodes/index.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/nodes/new.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/nodes/show.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/openid_consumer/index.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/openid_consumer/start.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/openid_login/index.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/openid_register/index.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/openid_register/show.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/openid_server/decide.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/roles/_form.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/roles/_navigation.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/roles/edit.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/roles/index.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/roles/new.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/roles/show.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/search/_search_form.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/search/index.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/search/show.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/search_entries/index.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/search_entries/show.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/app/views/status/index.html.haml</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/config/init.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/config/router.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/lib/chef-server-slice.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/lib/chef-server-slice/merbtasks.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/lib/chef-server-slice/slicetasks.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/lib/chef-server-slice/spectasks.rb</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/facebox/README.txt</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/facebox/b.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/facebox/bl.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/facebox/br.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/facebox/closelabel.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/facebox/facebox.css</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/facebox/facebox.js</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/facebox/loading.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/facebox/tl.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/facebox/tr.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/avatar.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/black_big.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/indicator.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/merb.jpg</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/toggle-collapse-dark.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/toggle-collapse-light.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/toggle-collapse.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/toggle-expand-dark.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/toggle-expand-light.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/toggle-expand.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/Thumbs.db</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/doc.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/docNode.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/docNodeLast.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/docNodeLastFirst.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/folder.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/folderNode.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/folderNodeFirst.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/folderNodeLast.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/folderNodeLastFirst.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/folderNodeOpen.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/folderNodeOpenFirst.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/folderNodeOpenLast.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/folderNodeOpenLastFirst.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/folderOpen.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/images/treeBuilderImages/vertLine.gif</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/javascripts/JSONeditor.js</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/javascripts/chef.js</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/javascripts/jquery-1.3.2.min.js</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/javascripts/jquery-ui-1.7.1.custom.min.js</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/javascripts/jquery.editinline.js</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/javascripts/jquery.jeditable.mini.js</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/javascripts/jquery.livequery.js</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/javascripts/jquery.localscroll.js</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/javascripts/jquery.scrollTo.js</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/javascripts/jquery.tools.min.js</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/javascripts/jquery.treeTable.min.js</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/base.css</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/chef.css</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-bg_diagonals-small_0_aaaaaa_40x40.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-bg_diagonals-thick_15_444444_40x40.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-bg_glass_100_f0f0f0_1x400.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-bg_glass_50_99c2ff_1x400.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-bg_glass_55_fbf5d0_1x400.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-bg_glass_80_e6e6e6_1x400.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-bg_glass_95_fef1ec_1x400.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-bg_highlight-hard_100_f9f9f9_1x100.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-bg_highlight-soft_100_e7eef3_1x100.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-icons_222222_256x240.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-icons_2694e8_256x240.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-icons_2e83ff_256x240.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-icons_72a7cf_256x240.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-icons_888888_256x240.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-icons_cd0a0a_256x240.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/images/ui-icons_ffffff_256x240.png</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/jquery-ui-1.7.1.custom.css</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/jquery.treeTable.css</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/themes/bec-green/style.css</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/themes/bec/style.css</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/themes/blue/style.css</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/themes/default/style.css</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/themes/djime-cerulean/style.css</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/themes/kathleene/style.css</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/themes/orange/style.css</filename>
    </removed>
    <removed>
      <filename>chef-server-slice/public/stylesheets/themes/reidb-greenish/style.css</filename>
    </removed>
    <removed>
      <filename>chef/lib/chef/application/indexer.rb</filename>
    </removed>
    <removed>
      <filename>chef/lib/chef/queue.rb</filename>
    </removed>
    <removed>
      <filename>chef/lib/chef/search.rb</filename>
    </removed>
    <removed>
      <filename>chef/lib/chef/search/result.rb</filename>
    </removed>
    <removed>
      <filename>chef/lib/chef/search_index.rb</filename>
    </removed>
    <removed>
      <filename>chef/spec/unit/application/indexer_spec.rb</filename>
    </removed>
    <removed>
      <filename>chef/spec/unit/queue_spec.rb</filename>
    </removed>
    <removed>
      <filename>chef/spec/unit/search/result_spec.rb</filename>
    </removed>
    <removed>
      <filename>features/steps/couchdb_steps.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>1404ace1ae1eb9bc43447342da2592fd1d802498</id>
    </parent>
    <parent>
      <id>b6ffd6b2cb69007994697144561f16f0debaff06</id>
    </parent>
  </parents>
  <author>
    <name>Adam Jacob</name>
    <email>adam@opscode.com</email>
  </author>
  <url>http://github.com/opscode/chef/commit/7971a7ccf8a8436aada34c810b93e013557e92cb</url>
  <id>7971a7ccf8a8436aada34c810b93e013557e92cb</id>
  <committed-date>2009-10-29T08:44:51-07:00</committed-date>
  <authored-date>2009-10-29T08:44:51-07:00</authored-date>
  <message>Merge branch 'master' into danielsdeleo/CHEF-626</message>
  <tree>018565f9a3b22be7d746ce10fad45c320a78a3ce</tree>
  <committer>
    <name>Adam Jacob</name>
    <email>adam@opscode.com</email>
  </committer>
</commit>
