From acb01cb80077ef0953fe0a9eeb0a8c6308d44d62 Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Tue, 31 Aug 2021 12:07:10 +0200 Subject: [PATCH] move salt-masterless provisioner out (#11229) * move salt-masterless provisioner out * go get github.com/hashicorp/packer-plugin-salt --- command/plugin.go | 2 - command/vendored_plugins.go | 2 + go.mod | 3 +- go.sum | 14 +- provisioner/salt-masterless/provisioner.go | 606 ------------------ .../salt-masterless/provisioner.hcl2spec.go | 79 --- .../salt-masterless/provisioner_test.go | 358 ----------- .../salt-masterless/version/version.go | 13 - .../docs/provisioners/salt-masterless.mdx | 121 ---- website/data/docs-nav-data.json | 4 - website/data/docs-remote-plugins.json | 7 + 11 files changed, 23 insertions(+), 1186 deletions(-) delete mode 100644 provisioner/salt-masterless/provisioner.go delete mode 100644 provisioner/salt-masterless/provisioner.hcl2spec.go delete mode 100644 provisioner/salt-masterless/provisioner_test.go delete mode 100644 provisioner/salt-masterless/version/version.go delete mode 100644 website/content/docs/provisioners/salt-masterless.mdx diff --git a/command/plugin.go b/command/plugin.go index a1842d495..ab5c21d31 100644 --- a/command/plugin.go +++ b/command/plugin.go @@ -24,7 +24,6 @@ import ( fileprovisioner "github.com/hashicorp/packer/provisioner/file" inspecprovisioner "github.com/hashicorp/packer/provisioner/inspec" powershellprovisioner "github.com/hashicorp/packer/provisioner/powershell" - saltmasterlessprovisioner "github.com/hashicorp/packer/provisioner/salt-masterless" shellprovisioner "github.com/hashicorp/packer/provisioner/shell" shelllocalprovisioner "github.com/hashicorp/packer/provisioner/shell-local" sleepprovisioner "github.com/hashicorp/packer/provisioner/sleep" @@ -46,7 +45,6 @@ var Provisioners = map[string]packersdk.Provisioner{ "file": new(fileprovisioner.Provisioner), "inspec": new(inspecprovisioner.Provisioner), "powershell": new(powershellprovisioner.Provisioner), - "salt-masterless": new(saltmasterlessprovisioner.Provisioner), "shell": new(shellprovisioner.Provisioner), "shell-local": new(shelllocalprovisioner.Provisioner), "sleep": new(sleepprovisioner.Provisioner), diff --git a/command/vendored_plugins.go b/command/vendored_plugins.go index 150d30fab..d9b48827c 100644 --- a/command/vendored_plugins.go +++ b/command/vendored_plugins.go @@ -62,6 +62,7 @@ import ( puppetmasterlessprovisioner "github.com/hashicorp/packer-plugin-puppet/provisioner/puppet-masterless" puppetserverprovisioner "github.com/hashicorp/packer-plugin-puppet/provisioner/puppet-server" qemubuilder "github.com/hashicorp/packer-plugin-qemu/builder/qemu" + saltmasterlessprovisioner "github.com/hashicorp/packer-plugin-salt/provisioner/salt-masterless" scalewaybuilder "github.com/hashicorp/packer-plugin-scaleway/builder/scaleway" tencentcloudcvmbuilder "github.com/hashicorp/packer-plugin-tencentcloud/builder/tencentcloud/cvm" tritonbuilder "github.com/hashicorp/packer-plugin-triton/builder/triton" @@ -157,6 +158,7 @@ var VendoredProvisioners = map[string]packersdk.Provisioner{ "converge": new(convergeprovisioner.Provisioner), "puppet-masterless": new(puppetmasterlessprovisioner.Provisioner), "puppet-server": new(puppetserverprovisioner.Provisioner), + "salt-masterless": new(saltmasterlessprovisioner.Provisioner), } // VendoredPostProcessors are post-processor components that were once bundled with the diff --git a/go.mod b/go.mod index 9dfb479e0..feaedb716 100644 --- a/go.mod +++ b/go.mod @@ -47,6 +47,7 @@ require ( github.com/hashicorp/packer-plugin-proxmox v1.0.0 github.com/hashicorp/packer-plugin-puppet v1.0.0 github.com/hashicorp/packer-plugin-qemu v1.0.0 + github.com/hashicorp/packer-plugin-salt v0.0.2 github.com/hashicorp/packer-plugin-scaleway v1.0.1 github.com/hashicorp/packer-plugin-sdk v0.2.3 github.com/hashicorp/packer-plugin-tencentcloud v1.0.1 @@ -71,7 +72,7 @@ require ( github.com/shirou/gopsutil v3.21.1+incompatible github.com/stretchr/testify v1.7.0 github.com/ulikunitz/xz v0.5.8 - github.com/zclconf/go-cty v1.9.0 + github.com/zclconf/go-cty v1.9.1 github.com/zclconf/go-cty-yaml v1.0.1 golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a golang.org/x/mod v0.4.1 diff --git a/go.sum b/go.sum index f904496ee..abd1dfba8 100644 --- a/go.sum +++ b/go.sum @@ -105,8 +105,9 @@ github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.0/go.mod h1:P+3VS0ETiQPyWOx3vB/oeC8J3qd7jnVZLYAFwWgGRt8= -github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.7 h1:Kpnbe19WkzVPpLLdAus4LkpNJ+pzLpfAViOUuvPcCqA= github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.7/go.mod h1:P+3VS0ETiQPyWOx3vB/oeC8J3qd7jnVZLYAFwWgGRt8= +github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.2.0 h1:c7GgSBfMt51UGM4SI1F7IFOokOVZO+uxNcJL3Xsmkp4= +github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.2.0/go.mod h1:P+3VS0ETiQPyWOx3vB/oeC8J3qd7jnVZLYAFwWgGRt8= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= @@ -732,13 +733,16 @@ github.com/hashicorp/packer v1.6.7-0.20210217093213-201869d627bf/go.mod h1:+EWPP github.com/hashicorp/packer v1.7.0/go.mod h1:3KRJcwOctl2JaAGpQMI1bWQRArfWNWqcYjO6AOsVVGQ= github.com/hashicorp/packer v1.7.1/go.mod h1:ApnmMINvuhhnfPyTVqZu6jznDWPVYDJUw7e188DFCmo= github.com/hashicorp/packer v1.7.2/go.mod h1:c/QB/DWK5fSdtNWrTb9etWacmbm01UY23ZILpGundCY= +github.com/hashicorp/packer v1.7.4/go.mod h1:uD7xkJ8yYOLUHEIOasoOXrIEmpdOibOIdwHUYroi6zc= github.com/hashicorp/packer-plugin-alicloud v1.0.0 h1:f1wyIqgSQQlpYs116Auq/FLYtrW3GbpTzxXxZWmNc1A= github.com/hashicorp/packer-plugin-alicloud v1.0.0/go.mod h1:wDWvfgD8JWdrGnAzO6SkcJJiAL+64SCEVY+DWcefNas= github.com/hashicorp/packer-plugin-amazon v0.0.1/go.mod h1:12c9msibyHdId+Mk/pCbdRb1KaLIhaNyxeJ6n8bZt30= +github.com/hashicorp/packer-plugin-amazon v1.0.0/go.mod h1:A4cjwkca0op3y/IWV3z9vTCHeJY2nLwBnwRxRFlFw6Y= github.com/hashicorp/packer-plugin-amazon v1.0.1-dev h1:dtCHPa+TfpbdbfqOm81PQ+kgF3gg9SdsWQcWRHaHAVw= github.com/hashicorp/packer-plugin-amazon v1.0.1-dev/go.mod h1:njc7Y7niDlf72TxK9Wl/ntfxbAF+R932sHjP5Kq8Tis= github.com/hashicorp/packer-plugin-ansible v1.0.0 h1:YU+k3JgwojL4Aw/yq6F9+b56B2wrhRfhQQgVCRRAZck= github.com/hashicorp/packer-plugin-ansible v1.0.0/go.mod h1:wbOfX8U2pcZdsChjwvvK62HF4C1hM4qcn1x5gjp87v0= +github.com/hashicorp/packer-plugin-azure v1.0.0/go.mod h1:zBhmvyDu5SxpGa97JKGtSmw5GObhW/BGZVHIt2YmlKo= github.com/hashicorp/packer-plugin-azure v1.0.1 h1:Vup22Vfcwmhm2nNQLQiVuZY47gnW6XlF1CTimdFJVac= github.com/hashicorp/packer-plugin-azure v1.0.1/go.mod h1:uFZJBJu9HDnHcG/laZNTmIUuqpSTvs+WtBwpLSH/Vkc= github.com/hashicorp/packer-plugin-chef v1.0.1 h1:sMTPzIAOaTlp4E05VZG6QILYUqR6IeBuszfHq3cdbUU= @@ -770,6 +774,7 @@ github.com/hashicorp/packer-plugin-lxc v1.0.0 h1:VZ98rBVCLpt5T/Z1DQYc+J/p7Fi6Rf3 github.com/hashicorp/packer-plugin-lxc v1.0.0/go.mod h1:fHqoE7MMNphPc8dZBs9dJZpfP+JciHQCXIq4bLS/SnE= github.com/hashicorp/packer-plugin-lxd v1.0.0 h1:hjSQGBWerBhtIZndw0iG4ubmRyb9Ih5KS8mng1YAu0w= github.com/hashicorp/packer-plugin-lxd v1.0.0/go.mod h1:jkBB4GnsoOrXZUFUiA1SOzj5Auk01MhpJiU6yIs5WJ4= +github.com/hashicorp/packer-plugin-ncloud v1.0.0/go.mod h1:kbCrWMogizFg0k+2x+vV74Nht5nak76g78h+N2sWOMA= github.com/hashicorp/packer-plugin-ncloud v1.0.1 h1:0oELREIthQEFSyLmoQxLwLhuf8JBVqsJ+PZnJ+zrsvc= github.com/hashicorp/packer-plugin-ncloud v1.0.1/go.mod h1:NH7KStfUBhi+Dky9KsJ8f2VvEefbKNyGBJvdpFC824E= github.com/hashicorp/packer-plugin-oneandone v1.0.0 h1:byuTophmj3/0faHfUQXEisxbZETuFWN3XTjmkoLxfKY= @@ -790,6 +795,8 @@ github.com/hashicorp/packer-plugin-puppet v1.0.0 h1:KxyUnFBIzF+nXPNtf+I+5p+IwaLs github.com/hashicorp/packer-plugin-puppet v1.0.0/go.mod h1:HRS/GxrY3iBINuTBgzOGR6jah+SRfqb37ixftZjZtJw= github.com/hashicorp/packer-plugin-qemu v1.0.0 h1:EiWFadbgahXzY15a6G1BJ49wsmqVYQViw/t9GtJibTo= github.com/hashicorp/packer-plugin-qemu v1.0.0/go.mod h1:U+IMWD5NjkCBNQIzttMPOQp+9Xzi4q/atkUJs2Nfv4s= +github.com/hashicorp/packer-plugin-salt v0.0.2 h1:MaXDObwd/Dwu0a/XX4AMr+6uL2Ms3AyUHrNWSn3sTgc= +github.com/hashicorp/packer-plugin-salt v0.0.2/go.mod h1:XYee5OuwqEaSoZGz2gUuT7KHKa08WEMEly4R+lMp380= github.com/hashicorp/packer-plugin-scaleway v1.0.1 h1:eklSsFnY/r94TilgPGTH2HOIYG1bZKBaofRxHBPo2zI= github.com/hashicorp/packer-plugin-scaleway v1.0.1/go.mod h1:kYoCKzb2GFDjqa4wPXGLjUM5lNzF/W7kcIoO13syJSY= github.com/hashicorp/packer-plugin-sdk v0.0.6/go.mod h1:Nvh28f+Jmpp2rcaN79bULTouNkGNDRfHckhHKTAXtyU= @@ -827,10 +834,12 @@ github.com/hashicorp/serf v0.9.2 h1:yJoyfZXo4Pk2p/M/viW+YLibBFiIbKoP79gu7kDAFP0= github.com/hashicorp/serf v0.9.2/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q= github.com/hashicorp/vault/api v1.0.5-0.20200519221902-385fac77e20f/go.mod h1:euTFbi2YJgwcju3imEt919lhJKF68nN1cQPq3aA+kBE= +github.com/hashicorp/vault/api v1.1.0/go.mod h1:R3Umvhlxi2TN7Ex2hzOowyeNb+SfbVWI973N+ctaFMk= github.com/hashicorp/vault/api v1.1.1 h1:907ld+Z9cALyvbZK2qUX9cLwvSaEQsMVQB3x2KE8+AI= github.com/hashicorp/vault/api v1.1.1/go.mod h1:29UXcn/1cLOPHQNMWA7bCz2By4PSd0VKPAydKXS5yN0= github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= github.com/hashicorp/vault/sdk v0.1.14-0.20200519221530-14615acda45f/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10= +github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10= github.com/hashicorp/vault/sdk v0.2.1 h1:S4O6Iv/dyKlE9AUTXGa7VOvZmsCvg36toPKgV4f2P4M= github.com/hashicorp/vault/sdk v0.2.1/go.mod h1:WfUiO1vYzfBkz1TmoE4ZGU7HD0T0Cl/rZwaxjBkgN4U= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= @@ -1233,8 +1242,9 @@ github.com/zclconf/go-cty v1.7.0/go.mod h1:VDR4+I79ubFBGm1uJac1226K5yANQFHeauxPB github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= github.com/zclconf/go-cty v1.8.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= github.com/zclconf/go-cty v1.8.3/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= -github.com/zclconf/go-cty v1.9.0 h1:IgJxw5b4LPXCPeqFjjhLaNEA8NKXMyaEUdAd399acts= github.com/zclconf/go-cty v1.9.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty v1.9.1 h1:viqrgQwFl5UpSxc046qblj78wZXVDFnSOufaOTER+cc= +github.com/zclconf/go-cty v1.9.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= github.com/zclconf/go-cty-yaml v1.0.1 h1:up11wlgAaDvlAGENcFDnZgkn0qUJurso7k6EpURKNF8= github.com/zclconf/go-cty-yaml v1.0.1/go.mod h1:IP3Ylp0wQpYm50IHK8OZWKMu6sPJIUgKa8XhiVHura0= diff --git a/provisioner/salt-masterless/provisioner.go b/provisioner/salt-masterless/provisioner.go deleted file mode 100644 index 0d653fcd2..000000000 --- a/provisioner/salt-masterless/provisioner.go +++ /dev/null @@ -1,606 +0,0 @@ -//go:generate packer-sdc mapstructure-to-hcl2 -type Config - -// This package implements a provisioner for Packer that executes a -// saltstack state within the remote machine -package saltmasterless - -import ( - "bytes" - "context" - "errors" - "fmt" - "os" - "path/filepath" - "regexp" - "strings" - - "github.com/hashicorp/go-getter/v2" - "github.com/hashicorp/hcl/v2/hcldec" - "github.com/hashicorp/packer-plugin-sdk/common" - "github.com/hashicorp/packer-plugin-sdk/guestexec" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/hashicorp/packer-plugin-sdk/template/config" - "github.com/hashicorp/packer-plugin-sdk/template/interpolate" -) - -type Config struct { - common.PackerConfig `mapstructure:",squash"` - - // If true, run the salt-bootstrap script - SkipBootstrap bool `mapstructure:"skip_bootstrap"` - BootstrapArgs string `mapstructure:"bootstrap_args"` - - DisableSudo bool `mapstructure:"disable_sudo"` - - // Custom state to run instead of highstate - CustomState string `mapstructure:"custom_state"` - - // Local path to the minion config - MinionConfig string `mapstructure:"minion_config"` - - // Local path to the minion grains - GrainsFile string `mapstructure:"grains_file"` - - // Local path to the salt state tree - LocalStateTree string `mapstructure:"local_state_tree"` - - // Local path to the salt pillar roots - LocalPillarRoots string `mapstructure:"local_pillar_roots"` - - // Remote path to the salt state tree - RemoteStateTree string `mapstructure:"remote_state_tree"` - - // Remote path to the salt pillar roots - RemotePillarRoots string `mapstructure:"remote_pillar_roots"` - - // Where files will be copied before moving to the /srv/salt directory - TempConfigDir string `mapstructure:"temp_config_dir"` - - // Don't exit packer if salt-call returns an error code - NoExitOnFailure bool `mapstructure:"no_exit_on_failure"` - - // Set the logging level for the salt-call run - LogLevel string `mapstructure:"log_level"` - - // Arguments to pass to salt-call - SaltCallArgs string `mapstructure:"salt_call_args"` - - // Directory containing salt-call - SaltBinDir string `mapstructure:"salt_bin_dir"` - - // Command line args passed onto salt-call - CmdArgs string `mapstructure-to-hcl2:",skip"` - - // The Guest OS Type (unix or windows) - GuestOSType string `mapstructure:"guest_os_type"` - - // An array of private or community git source formulas - Formulas []string `mapstructure:"formulas"` - - ctx interpolate.Context -} - -type Provisioner struct { - config Config - guestOSTypeConfig guestOSTypeConfig - guestCommands *guestexec.GuestCommands -} - -type guestOSTypeConfig struct { - tempDir string - stateRoot string - pillarRoot string - configDir string - bootstrapFetchCmd string - bootstrapRunCmd string -} - -var guestOSTypeConfigs = map[string]guestOSTypeConfig{ - guestexec.UnixOSType: { - configDir: "/etc/salt", - tempDir: "/tmp/salt", - stateRoot: "/srv/salt", - pillarRoot: "/srv/pillar", - bootstrapFetchCmd: "curl -L https://bootstrap.saltproject.io -o /tmp/install_salt.sh || wget -O /tmp/install_salt.sh https://bootstrap.saltproject.io", - bootstrapRunCmd: "sh /tmp/install_salt.sh", - }, - guestexec.WindowsOSType: { - configDir: "C:/salt/conf", - tempDir: "C:/Windows/Temp/salt/", - stateRoot: "C:/salt/state", - pillarRoot: "C:/salt/pillar/", - bootstrapFetchCmd: "powershell -Command \"[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Tls,Tls11,Tls12'; Invoke-WebRequest -Uri 'https://winbootstrap.saltproject.io' -OutFile 'C:/Windows/Temp/bootstrap-salt.ps1'\"", - bootstrapRunCmd: "Powershell C:/Windows/Temp/bootstrap-salt.ps1", - }, -} - -func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() } - -func (p *Provisioner) Prepare(raws ...interface{}) error { - err := config.Decode(&p.config, &config.DecodeOpts{ - PluginType: "salt-masterless", - Interpolate: true, - InterpolateContext: &p.config.ctx, - InterpolateFilter: &interpolate.RenderFilter{ - Exclude: []string{}, - }, - }, raws...) - if err != nil { - return err - } - - if p.config.GuestOSType == "" { - p.config.GuestOSType = guestexec.DefaultOSType - } else { - p.config.GuestOSType = strings.ToLower(p.config.GuestOSType) - } - - var ok bool - p.guestOSTypeConfig, ok = guestOSTypeConfigs[p.config.GuestOSType] - if !ok { - return fmt.Errorf("Invalid guest_os_type: \"%s\"", p.config.GuestOSType) - } - - p.guestCommands, err = guestexec.NewGuestCommands(p.config.GuestOSType, !p.config.DisableSudo) - if err != nil { - return fmt.Errorf("Invalid guest_os_type: \"%s\"", p.config.GuestOSType) - } - - if p.config.TempConfigDir == "" { - p.config.TempConfigDir = p.guestOSTypeConfig.tempDir - } - - var errs *packersdk.MultiError - - // require a salt state tree - err = validateDirConfig(p.config.LocalStateTree, "local_state_tree", true) - if err != nil { - errs = packersdk.MultiErrorAppend(errs, err) - } - - if p.config.Formulas != nil && len(p.config.Formulas) > 0 { - - validURLs := hasValidFormulaURLs(p.config.Formulas) - if !validURLs { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("Invalid formula URL. Please verify the git URLs also contain a '//' subdir")) - } - } - - err = validateDirConfig(p.config.LocalPillarRoots, "local_pillar_roots", false) - if err != nil { - errs = packersdk.MultiErrorAppend(errs, err) - } - - err = validateFileConfig(p.config.MinionConfig, "minion_config", false) - if err != nil { - errs = packersdk.MultiErrorAppend(errs, err) - } - - if p.config.MinionConfig != "" && (p.config.RemoteStateTree != "" || p.config.RemotePillarRoots != "") { - errs = packersdk.MultiErrorAppend(errs, - errors.New("remote_state_tree and remote_pillar_roots only apply when minion_config is not used")) - } - - err = validateFileConfig(p.config.GrainsFile, "grains_file", false) - if err != nil { - errs = packersdk.MultiErrorAppend(errs, err) - } - - // build the command line args to pass onto salt - var cmd_args bytes.Buffer - - if p.config.CustomState == "" { - cmd_args.WriteString(" state.highstate") - } else { - cmd_args.WriteString(" state.sls ") - cmd_args.WriteString(p.config.CustomState) - } - - if p.config.MinionConfig == "" { - // pass --file-root and --pillar-root if no minion_config is supplied - if p.config.RemoteStateTree != "" { - cmd_args.WriteString(" --file-root=") - cmd_args.WriteString(p.config.RemoteStateTree) - } else { - cmd_args.WriteString(" --file-root=") - cmd_args.WriteString(p.guestOSTypeConfig.stateRoot) - } - if p.config.RemotePillarRoots != "" { - cmd_args.WriteString(" --pillar-root=") - cmd_args.WriteString(p.config.RemotePillarRoots) - } else { - cmd_args.WriteString(" --pillar-root=") - cmd_args.WriteString(p.guestOSTypeConfig.pillarRoot) - } - } - - if !p.config.NoExitOnFailure { - cmd_args.WriteString(" --retcode-passthrough") - } - - if p.config.LogLevel == "" { - cmd_args.WriteString(" -l info") - } else { - cmd_args.WriteString(" -l ") - cmd_args.WriteString(p.config.LogLevel) - } - - if p.config.SaltCallArgs != "" { - cmd_args.WriteString(" ") - cmd_args.WriteString(p.config.SaltCallArgs) - } - - p.config.CmdArgs = cmd_args.String() - - if errs != nil && len(errs.Errors) > 0 { - return errs - } - - return nil -} - -func (p *Provisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packersdk.Communicator, _ map[string]interface{}) error { - var err error - var src, dst string - var formulas []string - - if p.config.Formulas != nil && len(p.config.Formulas) > 0 { - ui.Say("Downloading Salt formulas...") - client := new(getter.Client) - for _, i := range p.config.Formulas { - req := getter.Request{ - Src: i, - } - // Use //subdirectory name when creating in local_state_tree directory - state := strings.Split(i, "//") - last := state[len(state)-1] - path := filepath.Join(p.config.LocalStateTree, last) - formulas = append(formulas, path) - if _, err := os.Stat(path); os.IsNotExist(err) { - ui.Message(fmt.Sprintf("%s => %s", i, path)) - if err = os.Mkdir(path, 0755); err != nil { - return fmt.Errorf("Unable to create Salt state directory: %s", err) - } - req.Dst = path - req.GetMode = getter.ModeAny - if _, err := client.Get(ctx, &req); err != nil { - return fmt.Errorf("Unable to download Salt formula from %s: %s", i, err) - } - } else { - ui.Message(fmt.Sprintf("Found existing formula at: %s", path)) - } - } - } - - ui.Say("Provisioning with Salt...") - if !p.config.SkipBootstrap { - cmd := &packersdk.RemoteCmd{ - // Fallback on wget if curl failed for any reason (such as not being installed) - Command: fmt.Sprintf(p.guestOSTypeConfig.bootstrapFetchCmd), - } - ui.Message(fmt.Sprintf("Downloading saltstack bootstrap to /tmp/install_salt.sh")) - if err = cmd.RunWithUi(ctx, comm, ui); err != nil { - return fmt.Errorf("Unable to download Salt: %s", err) - } - cmd = &packersdk.RemoteCmd{ - Command: fmt.Sprintf("%s %s", p.sudo(p.guestOSTypeConfig.bootstrapRunCmd), p.config.BootstrapArgs), - } - ui.Message(fmt.Sprintf("Installing Salt with command %s", cmd.Command)) - if err = cmd.RunWithUi(ctx, comm, ui); err != nil { - return fmt.Errorf("Unable to install Salt: %s", err) - } - } - - ui.Message(fmt.Sprintf("Creating remote temporary directory: %s", p.config.TempConfigDir)) - if err := p.createDir(ui, comm, p.config.TempConfigDir); err != nil { - return fmt.Errorf("Error creating remote temporary directory: %s", err) - } - - if p.config.MinionConfig != "" { - ui.Message(fmt.Sprintf("Uploading minion config: %s", p.config.MinionConfig)) - src = p.config.MinionConfig - dst = filepath.ToSlash(filepath.Join(p.config.TempConfigDir, "minion")) - if err = p.uploadFile(ui, comm, dst, src); err != nil { - return fmt.Errorf("Error uploading local minion config file to remote: %s", err) - } - - // move minion config into /etc/salt - ui.Message(fmt.Sprintf("Make sure directory %s exists", p.guestOSTypeConfig.configDir)) - if err := p.createDir(ui, comm, p.guestOSTypeConfig.configDir); err != nil { - return fmt.Errorf("Error creating remote salt configuration directory: %s", err) - } - src = filepath.ToSlash(filepath.Join(p.config.TempConfigDir, "minion")) - dst = filepath.ToSlash(filepath.Join(p.guestOSTypeConfig.configDir, "minion")) - if err = p.moveFile(ui, comm, dst, src); err != nil { - return fmt.Errorf("Unable to move %s/minion to %s/minion: %s", p.config.TempConfigDir, p.guestOSTypeConfig.configDir, err) - } - } - - if p.config.GrainsFile != "" { - ui.Message(fmt.Sprintf("Uploading grains file: %s", p.config.GrainsFile)) - src = p.config.GrainsFile - dst = filepath.ToSlash(filepath.Join(p.config.TempConfigDir, "grains")) - if err = p.uploadFile(ui, comm, dst, src); err != nil { - return fmt.Errorf("Error uploading local grains file to remote: %s", err) - } - - // move grains file into /etc/salt - ui.Message(fmt.Sprintf("Make sure directory %s exists", p.guestOSTypeConfig.configDir)) - if err := p.createDir(ui, comm, p.guestOSTypeConfig.configDir); err != nil { - return fmt.Errorf("Error creating remote salt configuration directory: %s", err) - } - src = filepath.ToSlash(filepath.Join(p.config.TempConfigDir, "grains")) - dst = filepath.ToSlash(filepath.Join(p.guestOSTypeConfig.configDir, "grains")) - if err = p.moveFile(ui, comm, dst, src); err != nil { - return fmt.Errorf("Unable to move %s/grains to %s/grains: %s", p.config.TempConfigDir, p.guestOSTypeConfig.configDir, err) - } - } - - ui.Message(fmt.Sprintf("Uploading local state tree: %s", p.config.LocalStateTree)) - src = p.config.LocalStateTree - dst = filepath.ToSlash(filepath.Join(p.config.TempConfigDir, "states")) - if err = p.uploadDir(ui, comm, dst, src, []string{".git"}); err != nil { - return fmt.Errorf("Error uploading local state tree to remote: %s", err) - } - - // move state tree from temporary directory - src = filepath.ToSlash(filepath.Join(p.config.TempConfigDir, "states")) - if p.config.RemoteStateTree != "" { - dst = p.config.RemoteStateTree - } else { - dst = p.guestOSTypeConfig.stateRoot - } - - if err = p.statPath(ui, comm, dst); err != nil { - if err = p.removeDir(ui, comm, dst); err != nil { - return fmt.Errorf("Unable to clear salt tree: %s", err) - } - } - - if err = p.moveFile(ui, comm, dst, src); err != nil { - return fmt.Errorf("Unable to move %s/states to %s: %s", p.config.TempConfigDir, dst, err) - } - - // Remove the local Salt formulas if present - if p.config.Formulas != nil { - for _, f := range formulas { - if _, err := os.Stat(f); !os.IsNotExist(err) && f != p.config.LocalStateTree { - ui.Message(fmt.Sprintf("Removing Salt formula: %s", f)) - defer os.RemoveAll(f) - } - } - } - - if p.config.LocalPillarRoots != "" { - ui.Message(fmt.Sprintf("Uploading local pillar roots: %s", p.config.LocalPillarRoots)) - src = p.config.LocalPillarRoots - dst = filepath.ToSlash(filepath.Join(p.config.TempConfigDir, "pillar")) - if err = p.uploadDir(ui, comm, dst, src, []string{".git"}); err != nil { - return fmt.Errorf("Error uploading local pillar roots to remote: %s", err) - } - - // move pillar root from temporary directory - src = filepath.ToSlash(filepath.Join(p.config.TempConfigDir, "pillar")) - if p.config.RemotePillarRoots != "" { - dst = p.config.RemotePillarRoots - } else { - dst = p.guestOSTypeConfig.pillarRoot - } - - if err = p.statPath(ui, comm, dst); err != nil { - if err = p.removeDir(ui, comm, dst); err != nil { - return fmt.Errorf("Unable to clear pillar root: %s", err) - } - } - - if err = p.moveFile(ui, comm, dst, src); err != nil { - return fmt.Errorf("Unable to move %s/pillar to %s: %s", p.config.TempConfigDir, dst, err) - } - } - - if p.config.GuestOSType == guestexec.WindowsOSType { - ui.Message("Downloading Git for Windows") - cmd1 := &packersdk.RemoteCmd{Command: fmt.Sprintf("powershell [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri https://github.com/git-for-windows/git/releases/download/v2.28.0.windows.1/Git-2.28.0-64-bit.exe -OutFile $env:TEMP/Git.exe")} - if err = cmd1.RunWithUi(ctx, comm, ui); (err != nil || cmd1.ExitStatus() != 0) && !p.config.NoExitOnFailure { - if err == nil { - err = fmt.Errorf("Bad exit status: %d", cmd1.ExitStatus()) - } - - return fmt.Errorf("Unable to Download Git for Windows: %s", err) - } - - ui.Message("Installing Git for Windows") - cmd2 := &packersdk.RemoteCmd{Command: fmt.Sprintf("powershell Start-Process -FilePath $env:TEMP/Git.exe /SILENT -Wait")} - if err = cmd2.RunWithUi(ctx, comm, ui); (err != nil || cmd2.ExitStatus() != 0) && !p.config.NoExitOnFailure { - if err == nil { - err = fmt.Errorf("Bad exit status: %d", cmd2.ExitStatus()) - } - - return fmt.Errorf("Unable to Install Git for Windows: %s", err) - } - - ui.Message("Cleaning Up After Git for Windows") - cmd3 := &packersdk.RemoteCmd{Command: fmt.Sprintf("powershell Remove-Item $env:TEMP/Git.exe")} - if err = cmd3.RunWithUi(ctx, comm, ui); (err != nil || cmd3.ExitStatus() != 0) && !p.config.NoExitOnFailure { - if err == nil { - err = fmt.Errorf("Bad exit status: %d", cmd3.ExitStatus()) - } - - return fmt.Errorf("Unable to Clean-up After Git for Windows: %s", err) - } - - ui.Message("Running salt-call --local winrepo.update_git_repos") - cmd4 := &packersdk.RemoteCmd{Command: fmt.Sprintf("%s --local winrepo.update_git_repos", filepath.Join(p.config.SaltBinDir, "salt-call"))} - if err = cmd4.RunWithUi(ctx, comm, ui); (err != nil || cmd4.ExitStatus() != 0) && !p.config.NoExitOnFailure { - if err == nil { - err = fmt.Errorf("Bad exit status: %d", cmd4.ExitStatus()) - } - - return fmt.Errorf("Error executing salt-call --local winrepo.update_git_repos: %s", err) - } - - ui.Message("Running salt-call --local pkg.refresh_db") - cmd5 := &packersdk.RemoteCmd{Command: fmt.Sprintf("%s --local pkg.refresh_db", filepath.Join(p.config.SaltBinDir, "salt-call"))} - if err = cmd5.RunWithUi(ctx, comm, ui); (err != nil || cmd5.ExitStatus() != 0) && !p.config.NoExitOnFailure { - if err == nil { - err = fmt.Errorf("Bad exit status: %d", cmd5.ExitStatus()) - } - - return fmt.Errorf("Error executing salt-call --local pkg.refresh_db: %s", err) - } - } - - ui.Message(fmt.Sprintf("Running: salt-call --local %s", p.config.CmdArgs)) - cmd := &packersdk.RemoteCmd{Command: p.sudo(fmt.Sprintf("%s --local %s", filepath.Join(p.config.SaltBinDir, "salt-call"), p.config.CmdArgs))} - if err = cmd.RunWithUi(ctx, comm, ui); (err != nil || cmd.ExitStatus() != 0) && !p.config.NoExitOnFailure { - if err == nil { - err = fmt.Errorf("Bad exit status: %d", cmd.ExitStatus()) - } - - return fmt.Errorf("Error executing salt-call: %s", err) - } - - return nil -} - -// Prepends sudo to supplied command if config says to -func (p *Provisioner) sudo(cmd string) string { - if p.config.DisableSudo || (p.config.GuestOSType == guestexec.WindowsOSType) { - return cmd - } - - return "sudo " + cmd -} - -func validateDirConfig(path string, name string, required bool) error { - if required && path == "" { - return fmt.Errorf("%s cannot be empty", name) - } else if required == false && path == "" { - return nil - } - info, err := os.Stat(path) - if err != nil { - return fmt.Errorf("%s: path '%s' is invalid: %s", name, path, err) - } else if !info.IsDir() { - return fmt.Errorf("%s: path '%s' must point to a directory", name, path) - } - return nil -} - -func validateFileConfig(path string, name string, required bool) error { - if required == true && path == "" { - return fmt.Errorf("%s cannot be empty", name) - } else if required == false && path == "" { - return nil - } - info, err := os.Stat(path) - if err != nil { - return fmt.Errorf("%s: path '%s' is invalid: %s", name, path, err) - } else if info.IsDir() { - return fmt.Errorf("%s: path '%s' must point to a file", name, path) - } - return nil -} - -func hasValidFormulaURLs(s []string) bool { - re := regexp.MustCompile(`^(.*).git\/\/[a-zA-Z0-9-_]+(\?.*)?$`) - - for _, u := range s { - if !re.MatchString(u) { - return false - } - } - - return true -} - -func (p *Provisioner) uploadFile(ui packersdk.Ui, comm packersdk.Communicator, dst, src string) error { - f, err := os.Open(src) - if err != nil { - return fmt.Errorf("Error opening: %s", err) - } - defer f.Close() - - _, temp_dst := filepath.Split(dst) - - if err = comm.Upload(temp_dst, f, nil); err != nil { - return fmt.Errorf("Error uploading %s: %s", src, err) - } - - err = p.moveFile(ui, comm, dst, temp_dst) - if err != nil { - return fmt.Errorf("Error moving file to destination: %s", err) - } - - return nil -} - -func (p *Provisioner) moveFile(ui packersdk.Ui, comm packersdk.Communicator, dst string, src string) error { - ctx := context.TODO() - - ui.Message(fmt.Sprintf("Moving %s to %s", src, dst)) - cmd := &packersdk.RemoteCmd{ - Command: p.sudo(p.guestCommands.MovePath(src, dst)), - } - if err := cmd.RunWithUi(ctx, comm, ui); err != nil || cmd.ExitStatus() != 0 { - if err == nil { - err = fmt.Errorf("Bad exit status: %d", cmd.ExitStatus()) - } - - return fmt.Errorf("Unable to move %s to %s: %s", src, dst, err) - } - return nil -} - -func (p *Provisioner) createDir(ui packersdk.Ui, comm packersdk.Communicator, dir string) error { - ui.Message(fmt.Sprintf("Creating directory: %s", dir)) - cmd := &packersdk.RemoteCmd{ - Command: p.guestCommands.CreateDir(dir), - } - ctx := context.TODO() - if err := cmd.RunWithUi(ctx, comm, ui); err != nil { - return err - } - if cmd.ExitStatus() != 0 { - return fmt.Errorf("Non-zero exit status.") - } - return nil -} - -func (p *Provisioner) statPath(ui packersdk.Ui, comm packersdk.Communicator, path string) error { - ctx := context.TODO() - ui.Message(fmt.Sprintf("Verifying Path: %s", path)) - cmd := &packersdk.RemoteCmd{ - Command: p.guestCommands.StatPath(path), - } - if err := cmd.RunWithUi(ctx, comm, ui); err != nil { - return err - } - if cmd.ExitStatus() != 0 { - return fmt.Errorf("Non-zero exit status.") - } - return nil -} - -func (p *Provisioner) removeDir(ui packersdk.Ui, comm packersdk.Communicator, dir string) error { - ctx := context.TODO() - ui.Message(fmt.Sprintf("Removing directory: %s", dir)) - cmd := &packersdk.RemoteCmd{ - Command: p.guestCommands.RemoveDir(dir), - } - if err := cmd.RunWithUi(ctx, comm, ui); err != nil { - return err - } - if cmd.ExitStatus() != 0 { - return fmt.Errorf("Non-zero exit status.") - } - return nil -} - -func (p *Provisioner) uploadDir(ui packersdk.Ui, comm packersdk.Communicator, dst, src string, ignore []string) error { - _, temp_dst := filepath.Split(dst) - if err := comm.UploadDir(temp_dst, src, ignore); err != nil { - return err - } - return p.moveFile(ui, comm, dst, temp_dst) -} diff --git a/provisioner/salt-masterless/provisioner.hcl2spec.go b/provisioner/salt-masterless/provisioner.hcl2spec.go deleted file mode 100644 index dbc660ac4..000000000 --- a/provisioner/salt-masterless/provisioner.hcl2spec.go +++ /dev/null @@ -1,79 +0,0 @@ -// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT. - -package saltmasterless - -import ( - "github.com/hashicorp/hcl/v2/hcldec" - "github.com/zclconf/go-cty/cty" -) - -// FlatConfig is an auto-generated flat version of Config. -// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. -type FlatConfig struct { - PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"` - PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"` - PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"` - PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"` - PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"` - PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"` - PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"` - PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"` - SkipBootstrap *bool `mapstructure:"skip_bootstrap" cty:"skip_bootstrap" hcl:"skip_bootstrap"` - BootstrapArgs *string `mapstructure:"bootstrap_args" cty:"bootstrap_args" hcl:"bootstrap_args"` - DisableSudo *bool `mapstructure:"disable_sudo" cty:"disable_sudo" hcl:"disable_sudo"` - CustomState *string `mapstructure:"custom_state" cty:"custom_state" hcl:"custom_state"` - MinionConfig *string `mapstructure:"minion_config" cty:"minion_config" hcl:"minion_config"` - GrainsFile *string `mapstructure:"grains_file" cty:"grains_file" hcl:"grains_file"` - LocalStateTree *string `mapstructure:"local_state_tree" cty:"local_state_tree" hcl:"local_state_tree"` - LocalPillarRoots *string `mapstructure:"local_pillar_roots" cty:"local_pillar_roots" hcl:"local_pillar_roots"` - RemoteStateTree *string `mapstructure:"remote_state_tree" cty:"remote_state_tree" hcl:"remote_state_tree"` - RemotePillarRoots *string `mapstructure:"remote_pillar_roots" cty:"remote_pillar_roots" hcl:"remote_pillar_roots"` - TempConfigDir *string `mapstructure:"temp_config_dir" cty:"temp_config_dir" hcl:"temp_config_dir"` - NoExitOnFailure *bool `mapstructure:"no_exit_on_failure" cty:"no_exit_on_failure" hcl:"no_exit_on_failure"` - LogLevel *string `mapstructure:"log_level" cty:"log_level" hcl:"log_level"` - SaltCallArgs *string `mapstructure:"salt_call_args" cty:"salt_call_args" hcl:"salt_call_args"` - SaltBinDir *string `mapstructure:"salt_bin_dir" cty:"salt_bin_dir" hcl:"salt_bin_dir"` - GuestOSType *string `mapstructure:"guest_os_type" cty:"guest_os_type" hcl:"guest_os_type"` - Formulas []string `mapstructure:"formulas" cty:"formulas" hcl:"formulas"` -} - -// FlatMapstructure returns a new FlatConfig. -// FlatConfig is an auto-generated flat version of Config. -// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up. -func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } { - return new(FlatConfig) -} - -// HCL2Spec returns the hcl spec of a Config. -// This spec is used by HCL to read the fields of Config. -// The decoded values from this spec will then be applied to a FlatConfig. -func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { - s := map[string]hcldec.Spec{ - "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false}, - "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false}, - "packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false}, - "packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false}, - "packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false}, - "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, - "packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false}, - "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, - "skip_bootstrap": &hcldec.AttrSpec{Name: "skip_bootstrap", Type: cty.Bool, Required: false}, - "bootstrap_args": &hcldec.AttrSpec{Name: "bootstrap_args", Type: cty.String, Required: false}, - "disable_sudo": &hcldec.AttrSpec{Name: "disable_sudo", Type: cty.Bool, Required: false}, - "custom_state": &hcldec.AttrSpec{Name: "custom_state", Type: cty.String, Required: false}, - "minion_config": &hcldec.AttrSpec{Name: "minion_config", Type: cty.String, Required: false}, - "grains_file": &hcldec.AttrSpec{Name: "grains_file", Type: cty.String, Required: false}, - "local_state_tree": &hcldec.AttrSpec{Name: "local_state_tree", Type: cty.String, Required: false}, - "local_pillar_roots": &hcldec.AttrSpec{Name: "local_pillar_roots", Type: cty.String, Required: false}, - "remote_state_tree": &hcldec.AttrSpec{Name: "remote_state_tree", Type: cty.String, Required: false}, - "remote_pillar_roots": &hcldec.AttrSpec{Name: "remote_pillar_roots", Type: cty.String, Required: false}, - "temp_config_dir": &hcldec.AttrSpec{Name: "temp_config_dir", Type: cty.String, Required: false}, - "no_exit_on_failure": &hcldec.AttrSpec{Name: "no_exit_on_failure", Type: cty.Bool, Required: false}, - "log_level": &hcldec.AttrSpec{Name: "log_level", Type: cty.String, Required: false}, - "salt_call_args": &hcldec.AttrSpec{Name: "salt_call_args", Type: cty.String, Required: false}, - "salt_bin_dir": &hcldec.AttrSpec{Name: "salt_bin_dir", Type: cty.String, Required: false}, - "guest_os_type": &hcldec.AttrSpec{Name: "guest_os_type", Type: cty.String, Required: false}, - "formulas": &hcldec.AttrSpec{Name: "formulas", Type: cty.List(cty.String), Required: false}, - } - return s -} diff --git a/provisioner/salt-masterless/provisioner_test.go b/provisioner/salt-masterless/provisioner_test.go deleted file mode 100644 index 4aabf2c10..000000000 --- a/provisioner/salt-masterless/provisioner_test.go +++ /dev/null @@ -1,358 +0,0 @@ -package saltmasterless - -import ( - "io/ioutil" - "os" - "strings" - "testing" - - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -func testConfig() map[string]interface{} { - return map[string]interface{}{ - "local_state_tree": os.TempDir(), - } -} - -func TestProvisioner_Impl(t *testing.T) { - var raw interface{} - raw = &Provisioner{} - if _, ok := raw.(packersdk.Provisioner); !ok { - t.Fatalf("must be a Provisioner") - } -} - -func TestProvisionerPrepare_Defaults(t *testing.T) { - var p Provisioner - config := testConfig() - - err := p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - if p.config.TempConfigDir != p.guestOSTypeConfig.tempDir { - t.Errorf("unexpected temp config dir: %s", p.config.TempConfigDir) - } -} - -func TestProvisionerPrepare_InvalidKey(t *testing.T) { - var p Provisioner - config := testConfig() - - // Add a random key - config["i_should_not_be_valid"] = true - err := p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } -} - -func TestProvisionerPrepare_CustomState(t *testing.T) { - var p Provisioner - config := testConfig() - - err := p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - if !strings.Contains(p.config.CmdArgs, "state.") { - t.Fatal("a state should be specified in CmdArgs") - } - - config["custom_state"] = "birb" - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - if !strings.Contains(p.config.CmdArgs, "state.sls birb") { - t.Fatal("birb state should be specified in CmdArgs") - } -} - -func TestProvisionerPrepare_MinionConfig(t *testing.T) { - var p Provisioner - config := testConfig() - - config["minion_config"] = "/i/dont/exist/i/think" - err := p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - tf, err := ioutil.TempFile("", "minion") - if err != nil { - t.Fatalf("error tempfile: %s", err) - } - defer os.Remove(tf.Name()) - - config["minion_config"] = tf.Name() - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestProvisionerPrepare_MinionConfig_RemoteStateTree(t *testing.T) { - var p Provisioner - config := testConfig() - - config["minion_config"] = "/i/dont/exist/i/think" - config["remote_state_tree"] = "/i/dont/exist/remote_state_tree" - err := p.Prepare(config) - if err == nil { - t.Fatal("minion_config and remote_state_tree should cause error") - } -} - -func TestProvisionerPrepare_MinionConfig_RemotePillarRoots(t *testing.T) { - var p Provisioner - config := testConfig() - - config["minion_config"] = "/i/dont/exist/i/think" - config["remote_pillar_roots"] = "/i/dont/exist/remote_pillar_roots" - err := p.Prepare(config) - if err == nil { - t.Fatal("minion_config and remote_pillar_roots should cause error") - } -} - -func TestProvisionerPrepare_GrainsFile(t *testing.T) { - var p Provisioner - config := testConfig() - - config["grains_file"] = "/i/dont/exist/i/think" - err := p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - tf, err := ioutil.TempFile("", "grains") - if err != nil { - t.Fatalf("error tempfile: %s", err) - } - defer os.Remove(tf.Name()) - - config["grains_file"] = tf.Name() - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestProvisionerPrepare_LocalStateTree(t *testing.T) { - var p Provisioner - config := testConfig() - - config["local_state_tree"] = "/i/dont/exist/i/think" - err := p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - config["local_state_tree"] = os.TempDir() - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestProvisionerPrepare_LocalPillarRoots(t *testing.T) { - var p Provisioner - config := testConfig() - - config["local_pillar_roots"] = "/i/dont/exist/i/think" - err := p.Prepare(config) - if err == nil { - t.Fatal("should have error") - } - - config["local_pillar_roots"] = os.TempDir() - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestProvisionerSudo(t *testing.T) { - var p Provisioner - config := testConfig() - - err := p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - withSudo := p.sudo("echo hello") - if withSudo != "sudo echo hello" { - t.Fatalf("sudo command not generated correctly") - } - - config["disable_sudo"] = true - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - withoutSudo := p.sudo("echo hello") - if withoutSudo != "echo hello" { - t.Fatalf("sudo-less command not generated correctly") - } -} - -func TestProvisionerPrepare_RemoteStateTree(t *testing.T) { - var p Provisioner - config := testConfig() - - config["remote_state_tree"] = "/remote_state_tree" - err := p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - if !strings.Contains(p.config.CmdArgs, "--file-root=/remote_state_tree") { - t.Fatal("--file-root should be set in CmdArgs") - } -} - -func TestProvisionerPrepare_RemotePillarRoots(t *testing.T) { - var p Provisioner - config := testConfig() - - config["remote_pillar_roots"] = "/remote_pillar_roots" - err := p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - if !strings.Contains(p.config.CmdArgs, "--pillar-root=/remote_pillar_roots") { - t.Fatal("--pillar-root should be set in CmdArgs") - } -} - -func TestProvisionerPrepare_RemoteStateTree_Default(t *testing.T) { - var p Provisioner - config := testConfig() - - // no minion_config, no remote_state_tree - err := p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - if !strings.Contains(p.config.CmdArgs, "--file-root=/srv/salt") { - t.Fatal("--file-root should be set in CmdArgs") - } -} - -func TestProvisionerPrepare_RemotePillarRoots_Default(t *testing.T) { - var p Provisioner - config := testConfig() - - // no minion_config, no remote_pillar_roots - err := p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - if !strings.Contains(p.config.CmdArgs, "--pillar-root=/srv/pillar") { - t.Fatal("--pillar-root should be set in CmdArgs") - } -} - -func TestProvisionerPrepare_NoExitOnFailure(t *testing.T) { - var p Provisioner - config := testConfig() - - err := p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - if !strings.Contains(p.config.CmdArgs, "--retcode-passthrough") { - t.Fatal("--retcode-passthrough should be set in CmdArgs") - } - - config["no_exit_on_failure"] = true - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - if strings.Contains(p.config.CmdArgs, "--retcode-passthrough") { - t.Fatal("--retcode-passthrough should not be set in CmdArgs") - } -} - -func TestProvisionerPrepare_LogLevel(t *testing.T) { - var p Provisioner - config := testConfig() - - err := p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - if !strings.Contains(p.config.CmdArgs, "-l info") { - t.Fatal("-l info should be set in CmdArgs") - } - - config["log_level"] = "debug" - err = p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - if !strings.Contains(p.config.CmdArgs, "-l debug") { - t.Fatal("-l debug should be set in CmdArgs") - } -} - -func TestProvisionerPrepare_GuestOSType(t *testing.T) { - var p Provisioner - config := testConfig() - - config["guest_os_type"] = "Windows" - - err := p.Prepare(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - if p.config.GuestOSType != "windows" { - t.Fatalf("GuestOSType should be 'windows'") - } -} - -func TestProvisionerPrepare_BadFormulaURL(t *testing.T) { - var p Provisioner - config := testConfig() - - config["formulas"] = []string{ - "git::https://github.com/org/some-formula.git//", - } - - err := p.Prepare(config) - if err == nil { - t.Fatalf("Expected invalid formula URL: %s", err) - } -} - -func TestProvisionerPrepare_ValidFormulaURLs(t *testing.T) { - - var p Provisioner - config := testConfig() - - config["formulas"] = []string{ - "git::https://github.com/org/some-formula.git//example", - "git@github.com:org/some-formula.git//example", - "git::https://github.com/org/some-formula.git//example?ref=example", - } - - err := p.Prepare(config) - if err != nil { - t.Fatalf("Unexpected error in formula URLs: %s", err) - } -} diff --git a/provisioner/salt-masterless/version/version.go b/provisioner/salt-masterless/version/version.go deleted file mode 100644 index d61eb0409..000000000 --- a/provisioner/salt-masterless/version/version.go +++ /dev/null @@ -1,13 +0,0 @@ -package version - -import ( - "github.com/hashicorp/packer-plugin-sdk/version" - packerVersion "github.com/hashicorp/packer/version" -) - -var SaltPluginVersion *version.PluginVersion - -func init() { - SaltPluginVersion = version.InitializePluginVersion( - packerVersion.Version, packerVersion.VersionPrerelease) -} diff --git a/website/content/docs/provisioners/salt-masterless.mdx b/website/content/docs/provisioners/salt-masterless.mdx deleted file mode 100644 index 61d19fd2e..000000000 --- a/website/content/docs/provisioners/salt-masterless.mdx +++ /dev/null @@ -1,121 +0,0 @@ ---- -description: | - The salt-masterless Packer provisioner provisions machines built by Packer - using Salt states, without connecting to a Salt master. -page_title: Salt Masterless - Provisioners ---- - -# Salt Masterless Provisioner - -@include 'provisioners/unmaintained-plugin.mdx' - -Type: `salt-masterless` - -The `salt-masterless` Packer provisioner provisions machines built by Packer -using [Salt](https://saltproject.io/) states, without connecting to a Salt -master. - -## Basic Example - -The example below is fully functional. - - - - -```hcl -provisioner "salt-masterless" { - local_state_tree = "/Users/me/salt" -} -``` - - - - -```json -{ - "type": "salt-masterless", - "local_state_tree": "/Users/me/salt" -} -``` - - - - -## Configuration Reference - -The reference of available configuration options is listed below. The only -required element is "local_state_tree". - -Required: - -- `local_state_tree` (string) - The path to your local [state - tree](http://docs.saltproject.io/en/latest/ref/states/highstate.html#the-salt-state-tree). - This will be uploaded to the `remote_state_tree` on the remote. - -Optional: - -- `bootstrap_args` (string) - Arguments to send to the bootstrap script. - Usage is somewhat documented on - [github](https://github.com/saltstack/salt-bootstrap), but the [script - itself](https://github.com/saltstack/salt-bootstrap/blob/develop/bootstrap-salt.sh) - has more detailed usage instructions. By default, no arguments are sent to - the script. - -- `disable_sudo` (boolean) - By default, the bootstrap install command is - prefixed with `sudo`. When using a Docker builder, you will likely want to - pass `true` since `sudo` is often not pre-installed. - -- `remote_pillar_roots` (string) - The path to your remote [pillar - roots](http://docs.saltproject.io/en/latest/ref/configuration/master.html#pillar-configuration). - default: `/srv/pillar`. This option cannot be used with `minion_config`. - -- `remote_state_tree` (string) - The path to your remote [state - tree](http://docs.saltproject.io/en/latest/ref/states/highstate.html#the-salt-state-tree). - default: `/srv/salt`. This option cannot be used with `minion_config`. - -- `local_pillar_roots` (string) - The path to your local [pillar - roots](http://docs.saltproject.io/en/latest/ref/configuration/master.html#pillar-configuration). - This will be uploaded to the `remote_pillar_roots` on the remote. - -- `custom_state` (string) - A state to be run instead of `state.highstate`. - Defaults to `state.highstate` if unspecified. - -- `minion_config` (string) - The path to your local [minion config - file](http://docs.saltproject.io/en/latest/ref/configuration/minion.html). This will - be uploaded to the `/etc/salt` on the remote. This option overrides the - `remote_state_tree` or `remote_pillar_roots` options. - -- `grains_file` (string) - The path to your local [grains - file](https://docs.saltproject.io/en/latest/topics/grains). This will be - uploaded to `/etc/salt/grains` on the remote. - -- `skip_bootstrap` (boolean) - By default the salt provisioner runs [salt - bootstrap](https://github.com/saltstack/salt-bootstrap) to install salt. - Set this to true to skip this step. - -- `temp_config_dir` (string) - Where your local state tree will be copied - before moving to the `/srv/salt` directory. Default is `/tmp/salt`. - -- `no_exit_on_failure` (boolean) - Packer will exit if the `salt-call` - command fails. Set this option to true to ignore Salt failures. - -- `log_level` (string) - Set the logging level for the `salt-call` run. - -- `salt_call_args` (string) - Additional arguments to pass directly to - `salt-call`. See - [salt-call](https://docs.saltproject.io/en/latest/ref/cli/salt-call.html) - documentation for more information. By default no additional arguments - (besides the ones Packer generates) are passed to `salt-call`. - -- `salt_bin_dir` (string) - Path to the `salt-call` executable. Useful if it - is not on the PATH. - -- `guest_os_type` (string) - The target guest OS type, either "unix" or - "windows". - -- `formulas` (array of strings) - An array of git source formulas to be downloaded to the local - state tree prior to moving to the remote state tree. Note: `//directory` must be included in - the URL to download the appropriate formula directory. Example: - `git::https://github.com/saltstack-formulas/vault-formula.git//vault?ref=v1.2.3` - -@include 'provisioners/common-config.mdx' diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index 471da1596..f0358139e 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -737,10 +737,6 @@ "title": "PowerShell", "path": "provisioners/powershell" }, - { - "title": "Salt Masterless", - "path": "provisioners/salt-masterless" - }, { "title": "Shell", "path": "provisioners/shell" diff --git a/website/data/docs-remote-plugins.json b/website/data/docs-remote-plugins.json index 6a4352bf3..7d56fbf54 100644 --- a/website/data/docs-remote-plugins.json +++ b/website/data/docs-remote-plugins.json @@ -202,6 +202,13 @@ "repo": "hashicorp/packer-plugin-qemu", "version": "latest" }, + { + "title": "Salt", + "path": "salt", + "repo": "hashicorp/packer-plugin-salt", + "pluginTier": "community", + "version": "latest" + }, { "title": "Scaleway", "path": "scaleway",