package inspec import ( "crypto/rand" "fmt" "io" "io/ioutil" "os" "path" "strings" "testing" packersdk "github.com/hashicorp/packer/packer-plugin-sdk/packer" ) // Be sure to remove the InSpec stub file in each test with: // defer os.Remove(config["command"].(string)) func testConfig(t *testing.T) map[string]interface{} { m := make(map[string]interface{}) wd, err := os.Getwd() if err != nil { t.Fatalf("err: %s", err) } inspec_stub := path.Join(wd, "packer-inspec-stub.sh") err = ioutil.WriteFile(inspec_stub, []byte("#!/usr/bin/env bash\necho 2.2.16"), 0777) if err != nil { t.Fatalf("err: %s", err) } m["command"] = inspec_stub return m } 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(t) defer os.Remove(config["command"].(string)) err := p.Prepare(config) if err == nil { t.Fatalf("should have error") } hostkey_file, err := ioutil.TempFile("", "hostkey") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(hostkey_file.Name()) publickey_file, err := ioutil.TempFile("", "publickey") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(publickey_file.Name()) profile_file, err := ioutil.TempFile("", "test") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(profile_file.Name()) config["ssh_host_key_file"] = hostkey_file.Name() config["ssh_authorized_key_file"] = publickey_file.Name() config["profile"] = profile_file.Name() err = p.Prepare(config) if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(profile_file.Name()) err = os.Unsetenv("USER") if err != nil { t.Fatalf("err: %s", err) } err = p.Prepare(config) if err != nil { t.Fatalf("err: %s", err) } } func TestProvisionerPrepare_ProfileFile(t *testing.T) { var p Provisioner config := testConfig(t) defer os.Remove(config["command"].(string)) hostkey_file, err := ioutil.TempFile("", "hostkey") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(hostkey_file.Name()) publickey_file, err := ioutil.TempFile("", "publickey") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(publickey_file.Name()) config["ssh_host_key_file"] = hostkey_file.Name() config["ssh_authorized_key_file"] = publickey_file.Name() err = p.Prepare(config) if err == nil { t.Fatal("should have error") } profile_file, err := ioutil.TempFile("", "test") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(profile_file.Name()) config["profile"] = profile_file.Name() err = p.Prepare(config) if err != nil { t.Fatalf("err: %s", err) } test_dir, err := ioutil.TempDir("", "test") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(test_dir) config["profile"] = test_dir err = p.Prepare(config) if err != nil { t.Fatalf("err: %s", err) } } func TestProvisionerPrepare_HostKeyFile(t *testing.T) { var p Provisioner config := testConfig(t) defer os.Remove(config["command"].(string)) publickey_file, err := ioutil.TempFile("", "publickey") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(publickey_file.Name()) profile_file, err := ioutil.TempFile("", "test") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(profile_file.Name()) filename := make([]byte, 10) n, err := io.ReadFull(rand.Reader, filename) if n != len(filename) || err != nil { t.Fatal("could not create random file name") } config["ssh_host_key_file"] = fmt.Sprintf("%x", filename) config["ssh_authorized_key_file"] = publickey_file.Name() config["profile"] = profile_file.Name() err = p.Prepare(config) if err == nil { t.Fatal("should error if ssh_host_key_file does not exist") } hostkey_file, err := ioutil.TempFile("", "hostkey") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(hostkey_file.Name()) config["ssh_host_key_file"] = hostkey_file.Name() err = p.Prepare(config) if err != nil { t.Fatalf("err: %s", err) } } func TestProvisionerPrepare_AuthorizedKeyFiles(t *testing.T) { var p Provisioner config := testConfig(t) defer os.Remove(config["command"].(string)) hostkey_file, err := ioutil.TempFile("", "hostkey") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(hostkey_file.Name()) profile_file, err := ioutil.TempFile("", "test") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(profile_file.Name()) filename := make([]byte, 10) n, err := io.ReadFull(rand.Reader, filename) if n != len(filename) || err != nil { t.Fatal("could not create random file name") } config["ssh_host_key_file"] = hostkey_file.Name() config["profile"] = profile_file.Name() config["ssh_authorized_key_file"] = fmt.Sprintf("%x", filename) err = p.Prepare(config) if err == nil { t.Errorf("should error if ssh_authorized_key_file does not exist") } publickey_file, err := ioutil.TempFile("", "publickey") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(publickey_file.Name()) config["ssh_authorized_key_file"] = publickey_file.Name() err = p.Prepare(config) if err != nil { t.Errorf("err: %s", err) } } func TestProvisionerPrepare_LocalPort(t *testing.T) { var p Provisioner config := testConfig(t) defer os.Remove(config["command"].(string)) hostkey_file, err := ioutil.TempFile("", "hostkey") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(hostkey_file.Name()) publickey_file, err := ioutil.TempFile("", "publickey") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(publickey_file.Name()) profile_file, err := ioutil.TempFile("", "test") if err != nil { t.Fatalf("err: %s", err) } defer os.Remove(profile_file.Name()) config["ssh_host_key_file"] = hostkey_file.Name() config["ssh_authorized_key_file"] = publickey_file.Name() config["profile"] = profile_file.Name() config["local_port"] = 65537 err = p.Prepare(config) if err == nil { t.Fatal("should have error") } config["local_port"] = 22222 err = p.Prepare(config) if err != nil { t.Fatalf("err: %s", err) } } func TestInspecGetVersion(t *testing.T) { if os.Getenv("PACKER_ACC") == "" { t.Skip("This test is only run with PACKER_ACC=1 and it requires InSpec to be installed") } var p Provisioner p.config.Command = "inspec exec" err := p.getVersion() if err != nil { t.Fatalf("err: %s", err) } } func TestInspecGetVersionError(t *testing.T) { var p Provisioner p.config.Command = "./test-fixtures/exit1" err := p.getVersion() if err == nil { t.Fatal("Should return error") } if !strings.Contains(err.Error(), "./test-fixtures/exit1 version") { t.Fatal("Error message should include command name") } }