From dfc5e5cf948602ddcbf5a5dcdd158fbdd678a34f Mon Sep 17 00:00:00 2001 From: Aaron Walker Date: Fri, 17 May 2019 17:19:22 +0200 Subject: [PATCH 1/3] adds support for accepting the chef license --- provisioner/chef-client/provisioner.go | 10 +++++++ provisioner/chef-client/provisioner_test.go | 27 +++++++++++++++++++ provisioner/chef-solo/provisioner.go | 12 +++++++-- provisioner/chef-solo/provisioner_test.go | 27 +++++++++++++++++++ .../docs/provisioners/chef-client.html.md.erb | 8 ++++++ .../docs/provisioners/chef-solo.html.md.erb | 7 +++++ 6 files changed, 89 insertions(+), 2 deletions(-) diff --git a/provisioner/chef-client/provisioner.go b/provisioner/chef-client/provisioner.go index 147e1ffed..2bbaa6cca 100644 --- a/provisioner/chef-client/provisioner.go +++ b/provisioner/chef-client/provisioner.go @@ -50,6 +50,7 @@ type Config struct { Json map[string]interface{} ChefEnvironment string `mapstructure:"chef_environment"` + ChefLicense string `mapstructure:"chef_license"` ClientKey string `mapstructure:"client_key"` ConfigTemplate string `mapstructure:"config_template"` ElevatedUser string `mapstructure:"elevated_user"` @@ -87,6 +88,7 @@ type Provisioner struct { type ConfigTemplate struct { ChefEnvironment string + ChefLicense string ClientKey string EncryptedDataBagSecretPath string NodeName string @@ -194,6 +196,10 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { errs, fmt.Errorf("server_url must be set")) } + if p.config.ChefLicense == "" { + p.config.ChefLicense = "accept-silent" + } + if p.config.EncryptedDataBagSecretPath != "" { pFileInfo, err := os.Stat(p.config.EncryptedDataBagSecretPath) @@ -283,6 +289,7 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C nodeName, serverUrl, p.config.ClientKey, + p.config.ChefLicense, encryptedDataBagSecretPath, remoteValidationKeyPath, p.config.ValidationClientName, @@ -355,6 +362,7 @@ func (p *Provisioner) createConfig( nodeName string, serverUrl string, clientKey string, + chefLicense string, encryptedDataBagSecretPath, remoteKeyPath string, validationClientName string, @@ -388,6 +396,7 @@ func (p *Provisioner) createConfig( NodeName: nodeName, ServerUrl: serverUrl, ClientKey: clientKey, + ChefLicense: chefLicense, ValidationKeyPath: remoteKeyPath, ValidationClientName: validationClientName, ChefEnvironment: chefEnvironment, @@ -730,6 +739,7 @@ log_level :info log_location STDOUT chef_server_url "{{.ServerUrl}}" client_key "{{.ClientKey}}" +chef_license "{{.ChefLicense}}" {{if ne .EncryptedDataBagSecretPath ""}} encrypted_data_bag_secret "{{.EncryptedDataBagSecretPath}}" {{end}} diff --git a/provisioner/chef-client/provisioner_test.go b/provisioner/chef-client/provisioner_test.go index acb674b53..8bdfdd059 100644 --- a/provisioner/chef-client/provisioner_test.go +++ b/provisioner/chef-client/provisioner_test.go @@ -138,6 +138,33 @@ func TestProvisionerPrepare_serverUrl(t *testing.T) { t.Fatalf("err: %s", err) } } +func TestProvisionerPrepare_chefLicense(t *testing.T) { + var p Provisioner + + // Test not set + config := testConfig() + err := p.Prepare(config) + if err != nil { + t.Fatal("should error") + } + + if p.config.ChefLicense != "accept-silent" { + t.Fatalf("unexpected: %#v", p.config.ChefLicense) + } + + // Test set + config = testConfig() + config["chef_license"] = "accept" + p = Provisioner{} + err = p.Prepare(config) + if err != nil { + t.Fatalf("err: %s", err) + } + + if p.config.ChefLicense != "accept" { + t.Fatalf("unexpected: %#v", p.config.ChefLicense) + } +} func TestProvisionerPrepare_encryptedDataBagSecretPath(t *testing.T) { var err error diff --git a/provisioner/chef-solo/provisioner.go b/provisioner/chef-solo/provisioner.go index 712255cf4..df8cb7d33 100644 --- a/provisioner/chef-solo/provisioner.go +++ b/provisioner/chef-solo/provisioner.go @@ -43,6 +43,7 @@ type Config struct { common.PackerConfig `mapstructure:",squash"` ChefEnvironment string `mapstructure:"chef_environment"` + ChefLicense string `mapstructure:"chef_license"` ConfigTemplate string `mapstructure:"config_template"` CookbookPaths []string `mapstructure:"cookbook_paths"` RolesPath string `mapstructure:"roles_path"` @@ -76,6 +77,7 @@ type ConfigTemplate struct { RolesPath string EnvironmentsPath string ChefEnvironment string + ChefLicense string // Templates don't support boolean statements until Go 1.2. In the // mean time, we do this. @@ -144,6 +146,10 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { p.config.StagingDir = p.guestOSTypeConfig.stagingDir } + if p.config.ChefLicense == "" { + p.config.ChefLicense = "accept-silent" + } + var errs *packer.MultiError if p.config.ConfigTemplate != "" { fi, err := os.Stat(p.config.ConfigTemplate) @@ -283,7 +289,7 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C } } - configPath, err := p.createConfig(ui, comm, cookbookPaths, rolesPath, dataBagsPath, encryptedDataBagSecretPath, environmentsPath, p.config.ChefEnvironment) + configPath, err := p.createConfig(ui, comm, cookbookPaths, rolesPath, dataBagsPath, encryptedDataBagSecretPath, environmentsPath, p.config.ChefEnvironment, p.config.ChefLicense) if err != nil { return fmt.Errorf("Error creating Chef config file: %s", err) } @@ -324,7 +330,7 @@ func (p *Provisioner) uploadFile(ui packer.Ui, comm packer.Communicator, dst str return comm.Upload(dst, f, nil) } -func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, localCookbooks []string, rolesPath string, dataBagsPath string, encryptedDataBagSecretPath string, environmentsPath string, chefEnvironment string) (string, error) { +func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, localCookbooks []string, rolesPath string, dataBagsPath string, encryptedDataBagSecretPath string, environmentsPath string, chefEnvironment string, chefLicense string) (string, error) { ui.Message("Creating configuration file 'solo.rb'") cookbook_paths := make([]string, len(p.config.RemoteCookbookPaths)+len(localCookbooks)) @@ -365,6 +371,7 @@ func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, local HasEncryptedDataBagSecretPath: encryptedDataBagSecretPath != "", HasEnvironmentsPath: environmentsPath != "", ChefEnvironment: chefEnvironment, + ChefLicense: chefLicense, } configString, err := interpolate.Render(tpl, &p.config.ctx) if err != nil { @@ -569,6 +576,7 @@ func (p *Provisioner) processJsonUserVars() (map[string]interface{}, error) { } var DefaultConfigTemplate = ` +chef_license "{{.ChefLicense}}" cookbook_path [{{.CookbookPaths}}] {{if .HasRolesPath}} role_path "{{.RolesPath}}" diff --git a/provisioner/chef-solo/provisioner_test.go b/provisioner/chef-solo/provisioner_test.go index 01d237330..6fd9e7eee 100644 --- a/provisioner/chef-solo/provisioner_test.go +++ b/provisioner/chef-solo/provisioner_test.go @@ -35,6 +35,33 @@ func TestProvisionerPrepare_chefEnvironment(t *testing.T) { t.Fatalf("unexpected: %#v", p.config.ChefEnvironment) } } +func TestProvisionerPrepare_chefLicense(t *testing.T) { + var p Provisioner + + // Test not set + config := testConfig() + err := p.Prepare(config) + if err != nil { + t.Fatal("should error") + } + + if p.config.ChefLicense != "accept-silent" { + t.Fatalf("unexpected: %#v", p.config.ChefLicense) + } + + // Test set + config = testConfig() + config["chef_license"] = "accept" + p = Provisioner{} + err = p.Prepare(config) + if err != nil { + t.Fatalf("err: %s", err) + } + + if p.config.ChefLicense != "accept" { + t.Fatalf("unexpected: %#v", p.config.ChefLicense) + } +} func TestProvisionerPrepare_configTemplate(t *testing.T) { var err error diff --git a/website/source/docs/provisioners/chef-client.html.md.erb b/website/source/docs/provisioners/chef-client.html.md.erb index 803b346e6..fd09631b4 100644 --- a/website/source/docs/provisioners/chef-client.html.md.erb +++ b/website/source/docs/provisioners/chef-client.html.md.erb @@ -44,6 +44,12 @@ configuration is actually required. - `chef_environment` (string) - The name of the chef\_environment sent to the Chef server. By default this is empty and will not use an environment. +- `chef_license` (string) - As of Chef 15 chef requires a license be accepted + By default the chef_license with a value of accept-silent is set but possble + values are accept, accept-silent and accept-no-persist see + [Accepting the Chef License](https://docs.chef.io/chef_license_accept.html) + for details + - `config_template` (string) - Path to a template that will be used for the Chef configuration file. By default Packer only sets configuration it needs to match the settings set in the provisioner configuration. If you need to @@ -159,6 +165,7 @@ log_level :info log_location STDOUT chef_server_url "{{.ServerUrl}}" client_key "{{.ClientKey}}" +chef_license "{{.ChefLicense}}" {{if ne .EncryptedDataBagSecretPath ""}} encrypted_data_bag_secret "{{.EncryptedDataBagSecretPath}}" {{end}} @@ -192,6 +199,7 @@ This template is a [configuration template](/docs/templates/engine.html) and has a set of variables available to use: - `ChefEnvironment` - The Chef environment name. +- `ChefLicense` - The Chef license acceptance value. - `EncryptedDataBagSecretPath` - The path to the secret key file to decrypt encrypted data bags. - `NodeName` - The node name set in the configuration. diff --git a/website/source/docs/provisioners/chef-solo.html.md.erb b/website/source/docs/provisioners/chef-solo.html.md.erb index 44b4a3000..2856ec080 100644 --- a/website/source/docs/provisioners/chef-solo.html.md.erb +++ b/website/source/docs/provisioners/chef-solo.html.md.erb @@ -40,6 +40,12 @@ configuration is actually required, but at least `run_list` is recommended. - `chef_environment` (string) - The name of the `chef_environment` sent to the Chef server. By default this is empty and will not use an environment +- `chef_license` (string) - As of Chef 15 chef requires a license be accepted + By default the chef_license with a value of accept-silent is set but possble + values are accept, accept-silent and accept-no-persist see + [Accepting the Chef License](https://docs.chef.io/chef_license_accept.html) + for details + - `config_template` (string) - Path to a template that will be used for the Chef configuration file. By default Packer only sets configuration it needs to match the settings set in the provisioner configuration. If you need to @@ -131,6 +137,7 @@ has a set of variables available to use: - `ChefEnvironment` - The current enabled environment. Only non-empty if the environment path is set. +- `ChefLicense` - The Chef license acceptance value. - `CookbookPaths` is the set of cookbook paths ready to embedded directly into a Ruby array to configure Chef. - `DataBagsPath` is the path to the data bags folder. From 85b8a654b0f9e8e569cb0a5c90dcc3beb1c4253e Mon Sep 17 00:00:00 2001 From: Aaron Walker Date: Tue, 21 May 2019 15:26:07 +0200 Subject: [PATCH 2/3] only sets default value for chef license when installing chef and the install command is not set --- provisioner/chef-client/provisioner.go | 6 +++-- provisioner/chef-client/provisioner_test.go | 26 +++++++++++++++++++++ provisioner/chef-solo/provisioner.go | 6 +++-- provisioner/chef-solo/provisioner_test.go | 26 +++++++++++++++++++++ 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/provisioner/chef-client/provisioner.go b/provisioner/chef-client/provisioner.go index 2bbaa6cca..c08cff859 100644 --- a/provisioner/chef-client/provisioner.go +++ b/provisioner/chef-client/provisioner.go @@ -196,8 +196,10 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { errs, fmt.Errorf("server_url must be set")) } - if p.config.ChefLicense == "" { - p.config.ChefLicense = "accept-silent" + if p.config.SkipInstall == false && p.config.InstallCommand == p.guestOSTypeConfig.installCommand { + if p.config.ChefLicense == "" { + p.config.ChefLicense = "accept-silent" + } } if p.config.EncryptedDataBagSecretPath != "" { diff --git a/provisioner/chef-client/provisioner_test.go b/provisioner/chef-client/provisioner_test.go index 8bdfdd059..271726f3e 100644 --- a/provisioner/chef-client/provisioner_test.go +++ b/provisioner/chef-client/provisioner_test.go @@ -164,6 +164,32 @@ func TestProvisionerPrepare_chefLicense(t *testing.T) { if p.config.ChefLicense != "accept" { t.Fatalf("unexpected: %#v", p.config.ChefLicense) } + + // Test set skipInstall true + config = testConfig() + config["skip_install"] = true + p = Provisioner{} + err = p.Prepare(config) + if err != nil { + t.Fatalf("err: %s", err) + } + + if p.config.ChefLicense != "" { + t.Fatalf("unexpected: %#v", "empty string") + } + + // Test set installCommand true + config = testConfig() + config["install_command"] = "install chef" + p = Provisioner{} + err = p.Prepare(config) + if err != nil { + t.Fatalf("err: %s", err) + } + + if p.config.ChefLicense != "" { + t.Fatalf("unexpected: %#v", "empty string") + } } func TestProvisionerPrepare_encryptedDataBagSecretPath(t *testing.T) { diff --git a/provisioner/chef-solo/provisioner.go b/provisioner/chef-solo/provisioner.go index df8cb7d33..a28632466 100644 --- a/provisioner/chef-solo/provisioner.go +++ b/provisioner/chef-solo/provisioner.go @@ -146,8 +146,10 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { p.config.StagingDir = p.guestOSTypeConfig.stagingDir } - if p.config.ChefLicense == "" { - p.config.ChefLicense = "accept-silent" + if p.config.SkipInstall == false && p.config.InstallCommand == p.guestOSTypeConfig.installCommand { + if p.config.ChefLicense == "" { + p.config.ChefLicense = "accept-silent" + } } var errs *packer.MultiError diff --git a/provisioner/chef-solo/provisioner_test.go b/provisioner/chef-solo/provisioner_test.go index 6fd9e7eee..6df4c378c 100644 --- a/provisioner/chef-solo/provisioner_test.go +++ b/provisioner/chef-solo/provisioner_test.go @@ -61,6 +61,32 @@ func TestProvisionerPrepare_chefLicense(t *testing.T) { if p.config.ChefLicense != "accept" { t.Fatalf("unexpected: %#v", p.config.ChefLicense) } + + // Test set skipInstall true + config = testConfig() + config["skip_install"] = true + p = Provisioner{} + err = p.Prepare(config) + if err != nil { + t.Fatalf("err: %s", err) + } + + if p.config.ChefLicense != "" { + t.Fatalf("unexpected: %#v", "empty string") + } + + // Test set installCommand true + config = testConfig() + config["install_command"] = "install chef" + p = Provisioner{} + err = p.Prepare(config) + if err != nil { + t.Fatalf("err: %s", err) + } + + if p.config.ChefLicense != "" { + t.Fatalf("unexpected: %#v", "empty string") + } } func TestProvisionerPrepare_configTemplate(t *testing.T) { From c1141c849fd9ced3c8c6dd0bf59f9399a32ac8cd Mon Sep 17 00:00:00 2001 From: Aaron Walker Date: Fri, 24 May 2019 16:29:18 +0200 Subject: [PATCH 3/3] update docs --- .../source/docs/provisioners/chef-client.html.md.erb | 10 +++++----- website/source/docs/provisioners/chef-solo.html.md.erb | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/website/source/docs/provisioners/chef-client.html.md.erb b/website/source/docs/provisioners/chef-client.html.md.erb index fd09631b4..341f19da0 100644 --- a/website/source/docs/provisioners/chef-client.html.md.erb +++ b/website/source/docs/provisioners/chef-client.html.md.erb @@ -44,11 +44,11 @@ configuration is actually required. - `chef_environment` (string) - The name of the chef\_environment sent to the Chef server. By default this is empty and will not use an environment. -- `chef_license` (string) - As of Chef 15 chef requires a license be accepted - By default the chef_license with a value of accept-silent is set but possble - values are accept, accept-silent and accept-no-persist see - [Accepting the Chef License](https://docs.chef.io/chef_license_accept.html) - for details +- `chef_license` (string) - As of Chef v15, Chef requires users to accept a + license. Defaults to `accept-silent` when `skip_install` is false and + `install_command` is unset. Possible values are `accept`, + `accept-silent` and `accept-no-persist`. For details see [Accepting the + Chef License](https://docs.chef.io/chef_license_accept.html). - `config_template` (string) - Path to a template that will be used for the Chef configuration file. By default Packer only sets configuration it needs diff --git a/website/source/docs/provisioners/chef-solo.html.md.erb b/website/source/docs/provisioners/chef-solo.html.md.erb index 2856ec080..cb4836628 100644 --- a/website/source/docs/provisioners/chef-solo.html.md.erb +++ b/website/source/docs/provisioners/chef-solo.html.md.erb @@ -40,11 +40,11 @@ configuration is actually required, but at least `run_list` is recommended. - `chef_environment` (string) - The name of the `chef_environment` sent to the Chef server. By default this is empty and will not use an environment -- `chef_license` (string) - As of Chef 15 chef requires a license be accepted - By default the chef_license with a value of accept-silent is set but possble - values are accept, accept-silent and accept-no-persist see - [Accepting the Chef License](https://docs.chef.io/chef_license_accept.html) - for details +- `chef_license` (string) - As of Chef v15, Chef requires users to accept a + license. Defaults to `accept-silent` when `skip_install` is false and + `install_command` is unset. Possible values are `accept`, + `accept-silent` and `accept-no-persist`. For details see [Accepting the + Chef License](https://docs.chef.io/chef_license_accept.html). - `config_template` (string) - Path to a template that will be used for the Chef configuration file. By default Packer only sets configuration it needs