From 18438cf291f12bdc1d4341ceb7fcc44395a7835a Mon Sep 17 00:00:00 2001 From: "Schreiter, Wulf-Thilo" Date: Wed, 24 Jun 2015 13:46:59 +0200 Subject: [PATCH] Add knife config by template Since the chef-client provisioner is cleaning the node and client at the chef-server from the provisioned node it needs to have a flexible configuration This is replacing the used knife flags: -s '' -k '/tmp/packer-chef-client/client.pem' -u '' and puts their values into a generated knife.rb Additionally the knife.rb may include the optional ssl_verify_mode attribute to enable the verify mode verify_none Background: When deleting node and client to a self-hosted chef-server using self signed cerfiticates the usage of knife node delete -y -s '' -k '/tmp/packer-chef-client/client.pem' -u '' will lead into a ssl verification failure. The error output of the knife call is somthing like: 2015/06/24 12:29:17 ui: docker: WARNING: No knife configuration file found docker: WARNING: No knife configuration file found 2015/06/24 12:29:17 ui: docker: ERROR: SSL Validation failure connecting to host: 172.16.117.63 - SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed docker: ERROR: SSL Validation failure connecting to host: 172.16.117.63 - SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed 2015/06/24 12:29:17 ui: docker: ERROR: Could not establish a secure connection to the server. docker: ERROR: Could not establish a secure connection to the server. 2015/06/24 12:29:17 ui: docker: Use 'knife ssl check' to troubleshoot your SSL configuration. docker: Use 'knife ssl check' to troubleshoot your SSL configuration. 2015/06/24 12:29:17 ui: docker: If your Chef Server uses a self-signed certificate, you can use docker: If your Chef Server uses a self-signed certificate, you can use 2015/06/24 12:29:17 ui: docker: 'knife ssl fetch' to make knife trust the server's certificates. docker: 'knife ssl fetch' to make knife trust the server's certificates. 2015/06/24 12:29:17 ui: docker: docker: 2015/06/24 12:29:17 ui: docker: Original Exception: OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed docker: Original Exception: OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed 2015/06/24 12:29:17 packer-builder-docker: 2015/06/24 12:29:17 Executed command exit status: 100 --- provisioner/chef-client/provisioner.go | 61 +++++++++++++++++++++----- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/provisioner/chef-client/provisioner.go b/provisioner/chef-client/provisioner.go index 4d9430347..498033925 100644 --- a/provisioner/chef-client/provisioner.go +++ b/provisioner/chef-client/provisioner.go @@ -187,14 +187,20 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { } err = p.executeChef(ui, comm, configPath, jsonPath) + + knifeConfigPath, err2 := p.createKnifeConfig( + ui, comm, nodeName, serverUrl, p.config.ClientKey, p.config.SslVerifyMode) + if err2 != nil { + return fmt.Errorf("Error creating knife config on node: %s", err2) + } if !p.config.SkipCleanNode { - if err2 := p.cleanNode(ui, comm, nodeName); err2 != nil { + if err2 := p.cleanNode(ui, comm, nodeName, knifeConfigPath); err2 != nil { return fmt.Errorf("Error cleaning up chef node: %s", err2) } } if !p.config.SkipCleanClient { - if err2 := p.cleanClient(ui, comm, nodeName); err2 != nil { + if err2 := p.cleanClient(ui, comm, nodeName, knifeConfigPath); err2 != nil { return fmt.Errorf("Error cleaning up chef client: %s", err2) } } @@ -273,6 +279,32 @@ func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, nodeN return remotePath, nil } +func (p *Provisioner) createKnifeConfig(ui packer.Ui, comm packer.Communicator, nodeName string, serverUrl string, clientKey string, sslVerifyMode string) (string, error) { + ui.Message("Creating configuration file 'knife.rb'") + + // Read the template + tpl := DefaultKnifeTemplate + + ctx := p.config.ctx + ctx.Data = &ConfigTemplate{ + NodeName: nodeName, + ServerUrl: serverUrl, + ClientKey: clientKey, + SslVerifyMode: sslVerifyMode, + } + configString, err := interpolate.Render(tpl, &ctx) + if err != nil { + return "", err + } + + remotePath := filepath.ToSlash(filepath.Join(p.config.StagingDir, "knife.rb")) + if err := comm.Upload(remotePath, bytes.NewReader([]byte(configString)), nil); err != nil { + return "", err + } + + return remotePath, nil +} + func (p *Provisioner) createJson(ui packer.Ui, comm packer.Communicator) (string, error) { ui.Message("Creating JSON attribute file") @@ -334,32 +366,30 @@ func (p *Provisioner) createDir(ui packer.Ui, comm packer.Communicator, dir stri return nil } -func (p *Provisioner) cleanNode(ui packer.Ui, comm packer.Communicator, node string) error { +func (p *Provisioner) cleanNode(ui packer.Ui, comm packer.Communicator, node string, knifeConfigPath string) error { ui.Say("Cleaning up chef node...") args := []string{"node", "delete", node} - if err := p.knifeExec(ui, comm, node, args); err != nil { + if err := p.knifeExec(ui, comm, node, knifeConfigPath, args); err != nil { return fmt.Errorf("Failed to cleanup node: %s", err) } return nil } -func (p *Provisioner) cleanClient(ui packer.Ui, comm packer.Communicator, node string) error { +func (p *Provisioner) cleanClient(ui packer.Ui, comm packer.Communicator, node string, knifeConfigPath string) error { ui.Say("Cleaning up chef client...") args := []string{"client", "delete", node} - if err := p.knifeExec(ui, comm, node, args); err != nil { + if err := p.knifeExec(ui, comm, node, knifeConfigPath, args); err != nil { return fmt.Errorf("Failed to cleanup client: %s", err) } return nil } -func (p *Provisioner) knifeExec(ui packer.Ui, comm packer.Communicator, node string, args []string) error { +func (p *Provisioner) knifeExec(ui packer.Ui, comm packer.Communicator, node string, knifeConfigPath string, args []string) error { flags := []string{ "-y", - "-s", fmt.Sprintf("'%s'", p.config.ServerUrl), - "-k", fmt.Sprintf("'%s'", p.config.ClientKey), - "-u", fmt.Sprintf("'%s'", node), + "-c", knifeConfigPath, } cmdText := fmt.Sprintf( @@ -573,3 +603,14 @@ environment "{{.ChefEnvironment}}" ssl_verify_mode :{{.SslVerifyMode}} {{end}} ` + +var DefaultKnifeTemplate = ` +log_level :info +log_location STDOUT +chef_server_url "{{.ServerUrl}}" +client_key "{{.ClientKey}}" +node_name "{{.NodeName}}" +{{if ne .SslVerifyMode ""}} +ssl_verify_mode :{{.SslVerifyMode}} +{{end}} +`