{"action":"created","issue":{"url":"https://api.github.com/repos/chef/chef/issues/3385","labels_url":"https://api.github.com/repos/chef/chef/issues/3385/labels{/name}","comments_url":"https://api.github.com/repos/chef/chef/issues/3385/comments","events_url":"https://api.github.com/repos/chef/chef/issues/3385/events","html_url":"https://github.com/chef/chef/issues/3385","id":77782872,"number":3385,"title":"Creating an already existing node should fail?","user":{"login":"eitchugo","id":349457,"avatar_url":"https://avatars.githubusercontent.com/u/349457?v=3","gravatar_id":"","url":"https://api.github.com/users/eitchugo","html_url":"https://github.com/eitchugo","followers_url":"https://api.github.com/users/eitchugo/followers","following_url":"https://api.github.com/users/eitchugo/following{/other_user}","gists_url":"https://api.github.com/users/eitchugo/gists{/gist_id}","starred_url":"https://api.github.com/users/eitchugo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eitchugo/subscriptions","organizations_url":"https://api.github.com/users/eitchugo/orgs","repos_url":"https://api.github.com/users/eitchugo/repos","events_url":"https://api.github.com/users/eitchugo/events{/privacy}","received_events_url":"https://api.github.com/users/eitchugo/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-05-18T19:51:18Z","updated_at":"2015-05-29T19:18:27Z","closed_at":null,"body":"Hi!\r\n\r\nAt least on Chef 11.x, when I tried to create a new node with knife and it already existed, knife would return an error like this:\r\n\r\n```\r\n$ knife node create testing.localdomain --disable-editing\r\nERROR: Conflict\r\nResponse: Node already exists\r\n```\r\n\r\nThis also can happen if I try to create the node at the same time. I think it's the expected behavior.\r\n\r\nBut since Chef 12 (tested up to 12.0.8), no matter how many times or if a node already exists, knife will return OK:\r\n\r\n```\r\n$ knife node create testing.localdomain --disable-editing\r\nCreated node[testing.localdomain]\r\n```\r\n\r\nTurning on the DEBUG, I can see that:\r\n\r\n```\r\n# creating a node at the same time, with conflict\r\nDEBUG: HTTP 1.1 409 Conflict\r\nINFO: HTTP Request Returned 409 Conflict: Node already exists\r\n/usr/share/ruby/net/http/response.rb:119:in `error!': 409 \"Conflict\" (Net::HTTPServerException)\r\n...\r\n\r\n# creating a node at the same time, wiithout conflict\r\nDEBUG: HTTP 1.1 201 Created\r\n\r\n# creating a node that already exists, several seconds later+\r\nDEBUG: HTTP 1.1 200 OK \r\n```\r\n\r\nIsn't the correct behavior to return 409 Conflict instead of HTTP 200?\r\n\r\nMy use explanation:\r\n\r\nI'm using this to automatically name servers based on the last known server number, so I can create on-demand servers for autoscaling purposes. I'm using \"knife node create\" to reserve the name before renaming hostname, executing chef, and so on.\r\n\r\nWhen server returns HTTP 200 to knife, the node thinks he reserved its name and creates a race condition when multiple servers are ran at the same time: two nodes reserve the same name, but only one will use it."},"comment":{"url":"https://api.github.com/repos/chef/chef/issues/comments/106907093","html_url":"https://github.com/chef/chef/issues/3385#issuecomment-106907093","issue_url":"https://api.github.com/repos/chef/chef/issues/3385","id":106907093,"user":{"login":"sdelano","id":76847,"avatar_url":"https://avatars.githubusercontent.com/u/76847?v=3","gravatar_id":"","url":"https://api.github.com/users/sdelano","html_url":"https://github.com/sdelano","followers_url":"https://api.github.com/users/sdelano/followers","following_url":"https://api.github.com/users/sdelano/following{/other_user}","gists_url":"https://api.github.com/users/sdelano/gists{/gist_id}","starred_url":"https://api.github.com/users/sdelano/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sdelano/subscriptions","organizations_url":"https://api.github.com/users/sdelano/orgs","repos_url":"https://api.github.com/users/sdelano/repos","events_url":"https://api.github.com/users/sdelano/events{/privacy}","received_events_url":"https://api.github.com/users/sdelano/received_events","type":"User","site_admin":false},"created_at":"2015-05-29T19:18:27Z","updated_at":"2015-05-29T19:18:27Z","body":"I've tracked this down for someone to come along and fix if there is a solution that will work for everyone. I believe this has been the behavior for a long time, but I cannot confirm.\r\n\r\n`knife node create` executes the following [code](https://github.com/chef/chef/blob/master/lib/chef/knife/node_create.rb#L41-L43):\r\n\r\n```ruby\r\nnode = Chef::Node.new\r\nnode.name(@node_name)\r\ncreate_object(node)\r\n```\r\n\r\n`#create_object` comes from `chef/knife.rb` and executes the [following](https://github.com/chef/chef/blob/master/lib/chef/knife.rb#L521-L527):\r\n\r\n```ruby\r\noutput = edit_data(object)\r\n\r\nif Kernel.block_given?\r\n  output = block.call(output)\r\nelse\r\n  output.save\r\nend\r\n```\r\n\r\n`#edit_data` comes from `chef/knife/core/ui.rb` and returns the Chef object in question, in this case, a `Chef::Node` object. `Chef::Node#save` first attempts to update a node via PUT. If that fails, then a POST call is issued. [Here's](https://github.com/chef/chef/blob/master/lib/chef/node.rb#L527-L541) the code:\r\n\r\n```ruby\r\ndef save\r\n  # Try PUT. If the node doesn't yet exist, PUT will return 404,\r\n  # so then POST to create.\r\n  begin\r\n    if Chef::Config[:why_run]\r\n      Chef::Log.warn(\"In whyrun mode, so NOT performing node save.\")\r\n    else\r\n      chef_server_rest.put_rest(\"nodes/#{name}\", data_for_save)\r\n    end\r\n  rescue Net::HTTPServerException => e\r\n    raise e unless e.response.code == \"404\"\r\n    chef_server_rest.post_rest(\"nodes\", data_for_save)\r\n  end\r\n  self\r\nend\r\n```\r\n\r\nI don't know if there are historical reasons why we don't just call `Chef::Node#create` here instead."}}