hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io/
Other
42.6k stars 9.54k forks source link

provisioner/chef: node is deleted when `recreate_client=true` #13529

Closed jugatsu closed 7 years ago

jugatsu commented 7 years ago

Actually this is not bug but feature request.

I'm trying to completely replace knife bootstrap workflow with declarative description of this process with terraform. For new workflow i'm trying to use null_resource, chef provisioner and chef_node resource from chef provider.

resource "chef_node" "hyperv03" {
  name             = "hyperv03"
  environment_name = "${chef_environment.dev.name}"
  run_list = [
    "recipe[chef-client::delete_validation]",
    "recipe[chef-client::windows_service]"
  ]
}
resource "null_resource" "hyperv03" {

  depends_on = ["chef_node.hyperv03"]

  connection {
    type = "winrm"
    user = "vagrant"
    password = "vagrant"
    host = "192.168.33.11"
  }

    provisioner "chef" {
    run_list = []
    node_name = "${chef_node.hyperv03.name}"
    os_type = "windows"
    server_url = "https://api.chef.io/organizations/my_org"
    recreate_client = false
    skip_install = true
    skip_register = false
    user_name = "user"
    user_key = "${file(".chef/user.pem")}"
  }

}

So the problem is when i first create node with chef_node, the next run of chef provisioner re-create node. https://github.com/hashicorp/terraform/blob/master/builtin/provisioners/chef/resource_provisioner.go#L529 Why we should delete node if recreate_client=true? Why not just create only client? Maybe something like skip_node_deletion?

Terraform Version

Terraform v0.9.2

Affected Resource(s)

Please list the resources as a list, for example:

Expected Behavior

chef provisioner should only creates client but skip node deletion if node is already present.

Actual Behavior

chef provisioner deletes node.

References

mengesb commented 7 years ago

Provisioning is synonymous to bootstrapping, which means you need to have no node or client far as I know. The documentation also notes that it is not very useful:

Although this resource allows a node to be registered, it does not actually
configure the computer in question to interact with Chef. In most cases it
is better to use the chef provisioner to configure the Chef client on a
computer and have it register itself with the Chef server.

Generally speaking I'd use the provider to interact with only chef_environment, chef_role, chef_data_bag and chef_data_bag_item. If there was a corresponding chef_client provider then perhaps, but since this is left out there's a good chance it's for a good reason (perhaps it needs to be added? not sure; I've not seen a need to create the node and client separately). Likely the reason it doesn't exist is because of security for the node client pem certificate.

Why not just use the provisioner? It can set the run_list, handle both node and client sides of the setup, and provide for attributes via attributes_json. The only thing the provider gives you is cleanup on_destroy; and you're still missing the client. With new destroy provisioner I'd add that action to manually destroy via knife (as I do currently), but I also leave recreate_client = "true" in the event there's a conflict.

Your config, without the chef_node resource and cleaning up in the event of a destroy:

resource "null_resource" "hyperv03" {
  connection {
    type = "winrm"
    user = "vagrant"
    password = "vagrant"
    host = "192.168.33.11"
  }

  provisioner "chef" {
    environment = ""${chef_environment.dev.name}"
    run_list = ["recipe[chef-client::delete_validation]","recipe[chef-client::windows_service]"]
    node_name = "hyperv03"
    os_type = "windows"
    server_url = "https://api.chef.io/organizations/my_org"
    recreate_client = "true"
    skip_install = "true"
    user_name = "user"
    user_key = "${file(".chef/user.pem")}"
  }

  provisioner "local-exec" {
    when = "destroy"
    command = "knife node delete hyperv03 -y; knife client delete hyperv03 -y"
  }
}

There's the other matter of why you're doing this in a null_resource however the only situation where I've found it necessary would be during the creation of a chef-server itself (can't provision itself when you're creating all the keys and things in one invocation).

I'm also assuming due to sanitization you have .chef/user.pem; it would assume that in your presently operating directory is your file. If you don't already... I'd recommend that be a variable supplied through a private non-commited tfvars file as a variable. 👍

If you are looking for terraform guidance there's the chef community slack and a terraform channel where you can go seek out for input.

jugatsu commented 7 years ago

@mengesb Thanks a lot for your answer, really appreciate.

jugatsu commented 7 years ago

I will close this issue. It doesn't make much sense until chef_client resource will be implemented.

ghost commented 4 years ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.