Update plugin discover testing

* Add test case for loading plugin in CWD
* Add test case to validate checksume files are ignored
* Update Discover to include CWD "." in PluginFolders if KnowPluginFolders is unset
pull/12549/head
Wilken Rivera 3 years ago
parent a96584fb56
commit 848039dcdb

@ -85,7 +85,8 @@ func (c *PluginConfig) Discover() error {
}
if len(c.KnownPluginFolders) == 0 {
c.KnownPluginFolders = PluginFolders()
//PluginFolders should match the call in github.com/hahicorp/packer/main.go#loadConfig
c.KnownPluginFolders = PluginFolders(".")
}
// TODO after JSON is deprecated remove support for legacy component plugins.

@ -154,6 +154,233 @@ func TestDiscoverDatasource(t *testing.T) {
}
}
func TestMultiPlugin_describe(t *testing.T) {
createMockPlugins(t, mockPlugins)
pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
defer os.RemoveAll(pluginDir)
c := PluginConfig{}
err := c.Discover()
if err != nil {
t.Fatalf("error discovering plugins; %s", err.Error())
}
for mockPluginName, plugin := range mockPlugins {
for mockBuilderName := range plugin.Builders {
expectedBuilderName := mockPluginName + "-" + mockBuilderName
if !c.Builders.Has(expectedBuilderName) {
t.Fatalf("expected to find builder %q", expectedBuilderName)
}
}
for mockProvisionerName := range plugin.Provisioners {
expectedProvisionerName := mockPluginName + "-" + mockProvisionerName
if !c.Provisioners.Has(expectedProvisionerName) {
t.Fatalf("expected to find builder %q", expectedProvisionerName)
}
}
for mockPostProcessorName := range plugin.PostProcessors {
expectedPostProcessorName := mockPluginName + "-" + mockPostProcessorName
if !c.PostProcessors.Has(expectedPostProcessorName) {
t.Fatalf("expected to find post-processor %q", expectedPostProcessorName)
}
}
for mockDatasourceName := range plugin.Datasources {
expectedDatasourceName := mockPluginName + "-" + mockDatasourceName
if !c.DataSources.Has(expectedDatasourceName) {
t.Fatalf("expected to find datasource %q", expectedDatasourceName)
}
}
}
}
func TestMultiPlugin_describe_installed(t *testing.T) {
createMockInstalledPlugins(t, mockInstalledPlugins, createMockChecksumFile)
pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
defer os.RemoveAll(pluginDir)
c := PluginConfig{}
err := c.Discover()
if err != nil {
t.Fatalf("error discovering plugins; %s", err.Error())
}
for mockPluginName, plugin := range mockInstalledPlugins {
mockPluginName = strings.Split(mockPluginName, "_")[0]
for mockBuilderName := range plugin.Builders {
expectedBuilderName := mockPluginName + "-" + mockBuilderName
if !c.Builders.Has(expectedBuilderName) {
t.Fatalf("expected to find builder %q", expectedBuilderName)
}
}
for mockProvisionerName := range plugin.Provisioners {
expectedProvisionerName := mockPluginName + "-" + mockProvisionerName
if !c.Provisioners.Has(expectedProvisionerName) {
t.Fatalf("expected to find builder %q", expectedProvisionerName)
}
}
for mockPostProcessorName := range plugin.PostProcessors {
expectedPostProcessorName := mockPluginName + "-" + mockPostProcessorName
if !c.PostProcessors.Has(expectedPostProcessorName) {
t.Fatalf("expected to find post-processor %q", expectedPostProcessorName)
}
}
for mockDatasourceName := range plugin.Datasources {
expectedDatasourceName := mockPluginName + "-" + mockDatasourceName
if !c.DataSources.Has(expectedDatasourceName) {
t.Fatalf("expected to find datasource %q", expectedDatasourceName)
}
}
}
}
func TestMultiPlugin_describe_installed_for_invalid(t *testing.T) {
tc := []struct {
desc string
installedPluginsMock map[string]pluginsdk.Set
createMockFn func(*testing.T, map[string]pluginsdk.Set)
}{
{
desc: "Incorrectly named plugins",
installedPluginsMock: invalidInstalledPluginsMock,
createMockFn: func(t *testing.T, mocks map[string]pluginsdk.Set) {
createMockInstalledPlugins(t, mocks, createMockChecksumFile)
},
},
{
desc: "Plugins missing checksums",
installedPluginsMock: mockInstalledPlugins,
createMockFn: func(t *testing.T, mocks map[string]pluginsdk.Set) {
createMockInstalledPlugins(t, mocks)
},
},
}
for _, tt := range tc {
t.Run(tt.desc, func(t *testing.T) {
tt.createMockFn(t, tt.installedPluginsMock)
pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
defer os.RemoveAll(pluginDir)
c := PluginConfig{}
err := c.Discover()
if err != nil {
t.Fatalf("error discovering plugins; %s", err.Error())
}
if c.Builders.Has("feather") {
t.Fatalf("expected to not find builder %q", "feather")
}
for mockPluginName, plugin := range tt.installedPluginsMock {
mockPluginName = strings.Split(mockPluginName, "_")[0]
for mockBuilderName := range plugin.Builders {
expectedBuilderName := mockPluginName + "-" + mockBuilderName
if c.Builders.Has(expectedBuilderName) {
t.Fatalf("expected to not find builder %q", expectedBuilderName)
}
}
for mockProvisionerName := range plugin.Provisioners {
expectedProvisionerName := mockPluginName + "-" + mockProvisionerName
if c.Provisioners.Has(expectedProvisionerName) {
t.Fatalf("expected to not find builder %q", expectedProvisionerName)
}
}
for mockPostProcessorName := range plugin.PostProcessors {
expectedPostProcessorName := mockPluginName + "-" + mockPostProcessorName
if c.PostProcessors.Has(expectedPostProcessorName) {
t.Fatalf("expected to not find post-processor %q", expectedPostProcessorName)
}
}
for mockDatasourceName := range plugin.Datasources {
expectedDatasourceName := mockPluginName + "-" + mockDatasourceName
if c.DataSources.Has(expectedDatasourceName) {
t.Fatalf("expected to not find datasource %q", expectedDatasourceName)
}
}
}
})
}
}
func TestMultiPlugin_defaultName(t *testing.T) {
createMockPlugins(t, defaultNameMock)
pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
defer os.RemoveAll(pluginDir)
c := PluginConfig{}
err := c.Discover()
if err != nil {
t.Fatalf("error discovering plugins; %s ; mocks are %#v", err.Error(), defaultNameMock)
}
expectedBuilderNames := []string{"foo-bar", "foo-baz", "foo"}
for _, mockBuilderName := range expectedBuilderNames {
if !c.Builders.Has(mockBuilderName) {
t.Fatalf("expected to find builder %q; builders is %#v", mockBuilderName, c.Builders)
}
}
}
// no T.Parallel using os.Chdir
func TestMultiPlugin_CWD(t *testing.T) {
createMockPlugins(t, defaultNameMock)
pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
defer os.RemoveAll(pluginDir)
// Unset PACKER_PLUGIN_PATH to test CWD loading
os.Unsetenv("PACKER_PLUGIN_PATH")
if err := os.Chdir(pluginDir); err != nil {
t.Fatalf("failed to change directory to test loading from CWD: %s", err)
}
c := PluginConfig{}
err := c.Discover()
if err != nil {
t.Fatalf("error discovering plugins; %s ; mocks are %#v", err.Error(), defaultNameMock)
}
expectedBuilderNames := []string{"foo-bar", "foo-baz", "foo"}
for _, mockBuilderName := range expectedBuilderNames {
if !c.Builders.Has(mockBuilderName) {
t.Fatalf("expected to find builder %q; builders is %#v", mockBuilderName, c.Builders)
}
}
}
func TestMultiPlugin_IgnoreChecksumFile(t *testing.T) {
createMockPlugins(t, defaultNameMock)
pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
defer os.RemoveAll(pluginDir)
csFile, err := generateMockChecksumFile(filepath.Join(pluginDir, "packer-plugin-foo"))
if err != nil {
t.Fatal(err.Error())
}
// Copy plugin contents into checksum file to validate that it is not only skipped but that it never gets loaded
if err := os.Rename(filepath.Join(pluginDir, "packer-plugin-foo"), csFile); err != nil {
t.Fatalf("failed to rename plugin bin file to checkfum file needed for test: %s", err)
}
c := PluginConfig{}
err = c.Discover()
if err != nil {
t.Fatalf("error discovering plugins; %s ; mocks are %#v", err.Error(), defaultNameMock)
}
expectedBuilderNames := []string{"foo-bar", "foo-baz", "foo"}
for _, mockBuilderName := range expectedBuilderNames {
if c.Builders.Has(mockBuilderName) {
t.Fatalf("expected to not find builder %q; builders is %#v", mockBuilderName, c.Builders)
}
}
}
func TestMultiPlugin_defaultName_each_plugin_type(t *testing.T) {
createMockPlugins(t, doubleDefaultMock)
pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
defer os.RemoveAll(pluginDir)
c := PluginConfig{}
err := c.Discover()
if err != nil {
t.Fatal("Should not have error because pluginsdk.DEFAULT_NAME is used twice but only once per plugin type.")
}
}
func generateFakePlugins(dirname string, pluginNames []string) (string, []string, func(), error) {
dir, err := os.MkdirTemp("", dirname)
if err != nil {
@ -296,6 +523,15 @@ func createMockPlugins(t *testing.T, plugins map[string]pluginsdk.Set) {
}
func createMockChecksumFile(t testing.TB, filePath string) {
t.Helper()
cs, err := generateMockChecksumFile(filePath)
if err != nil {
t.Fatalf(err.Error())
}
t.Logf("created fake plugin checksum file %s", cs)
}
func generateMockChecksumFile(filePath string) (string, error) {
cs := plugingetter.Checksummer{
Type: "sha256",
Hash: sha256.New(),
@ -303,19 +539,20 @@ func createMockChecksumFile(t testing.TB, filePath string) {
f, err := os.Open(filePath)
if err != nil {
t.Fatalf("failed to open fake plugin binary: %v", err)
return "", fmt.Errorf("failed to open fake plugin binary: %v", err)
}
defer f.Close()
sum, err := cs.Sum(f)
if err != nil {
t.Fatalf("failed to checksum fake plugin binary: %v", err)
return "", fmt.Errorf("failed to checksum fake plugin binary: %v", err)
}
t.Logf("creating fake plugin checksum file %s with contents %x", filePath+cs.FileExt(), string(sum))
if err := os.WriteFile(filePath+cs.FileExt(), []byte(fmt.Sprintf("%x", sum)), os.ModePerm); err != nil {
t.Fatalf("failed to write checksum fake plugin binary: %v", err)
sumfile := filePath + cs.FileExt()
if err := os.WriteFile(sumfile, []byte(fmt.Sprintf("%x", sum)), os.ModePerm); err != nil {
return "", fmt.Errorf("failed to write checksum fake plugin binary: %v", err)
}
return sumfile, nil
}
func createMockInstalledPlugins(t *testing.T, plugins map[string]pluginsdk.Set, opts ...func(tb testing.TB, filePath string)) {
@ -461,180 +698,3 @@ var (
},
}
)
func Test_multiplugin_describe(t *testing.T) {
createMockPlugins(t, mockPlugins)
pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
defer os.RemoveAll(pluginDir)
c := PluginConfig{}
err := c.Discover()
if err != nil {
t.Fatalf("error discovering plugins; %s", err.Error())
}
for mockPluginName, plugin := range mockPlugins {
for mockBuilderName := range plugin.Builders {
expectedBuilderName := mockPluginName + "-" + mockBuilderName
if !c.Builders.Has(expectedBuilderName) {
t.Fatalf("expected to find builder %q", expectedBuilderName)
}
}
for mockProvisionerName := range plugin.Provisioners {
expectedProvisionerName := mockPluginName + "-" + mockProvisionerName
if !c.Provisioners.Has(expectedProvisionerName) {
t.Fatalf("expected to find builder %q", expectedProvisionerName)
}
}
for mockPostProcessorName := range plugin.PostProcessors {
expectedPostProcessorName := mockPluginName + "-" + mockPostProcessorName
if !c.PostProcessors.Has(expectedPostProcessorName) {
t.Fatalf("expected to find post-processor %q", expectedPostProcessorName)
}
}
for mockDatasourceName := range plugin.Datasources {
expectedDatasourceName := mockPluginName + "-" + mockDatasourceName
if !c.DataSources.Has(expectedDatasourceName) {
t.Fatalf("expected to find datasource %q", expectedDatasourceName)
}
}
}
}
func Test_multiplugin_describe_installed(t *testing.T) {
createMockInstalledPlugins(t, mockInstalledPlugins, createMockChecksumFile)
pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
defer os.RemoveAll(pluginDir)
c := PluginConfig{}
err := c.Discover()
if err != nil {
t.Fatalf("error discovering plugins; %s", err.Error())
}
for mockPluginName, plugin := range mockInstalledPlugins {
mockPluginName = strings.Split(mockPluginName, "_")[0]
for mockBuilderName := range plugin.Builders {
expectedBuilderName := mockPluginName + "-" + mockBuilderName
if !c.Builders.Has(expectedBuilderName) {
t.Fatalf("expected to find builder %q", expectedBuilderName)
}
}
for mockProvisionerName := range plugin.Provisioners {
expectedProvisionerName := mockPluginName + "-" + mockProvisionerName
if !c.Provisioners.Has(expectedProvisionerName) {
t.Fatalf("expected to find builder %q", expectedProvisionerName)
}
}
for mockPostProcessorName := range plugin.PostProcessors {
expectedPostProcessorName := mockPluginName + "-" + mockPostProcessorName
if !c.PostProcessors.Has(expectedPostProcessorName) {
t.Fatalf("expected to find post-processor %q", expectedPostProcessorName)
}
}
for mockDatasourceName := range plugin.Datasources {
expectedDatasourceName := mockPluginName + "-" + mockDatasourceName
if !c.DataSources.Has(expectedDatasourceName) {
t.Fatalf("expected to find datasource %q", expectedDatasourceName)
}
}
}
}
func Test_multiplugin_describe_installed_for_invalid(t *testing.T) {
tc := []struct {
desc string
installedPluginsMock map[string]pluginsdk.Set
createMockFn func(*testing.T, map[string]pluginsdk.Set)
}{
{
desc: "Incorrectly named plugins",
installedPluginsMock: invalidInstalledPluginsMock,
createMockFn: func(t *testing.T, mocks map[string]pluginsdk.Set) {
createMockInstalledPlugins(t, mocks, createMockChecksumFile)
},
},
{
desc: "Plugins missing checksums",
installedPluginsMock: mockInstalledPlugins,
createMockFn: func(t *testing.T, mocks map[string]pluginsdk.Set) {
createMockInstalledPlugins(t, mocks)
},
},
}
for _, tt := range tc {
t.Run(tt.desc, func(t *testing.T) {
tt.createMockFn(t, tt.installedPluginsMock)
pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
defer os.RemoveAll(pluginDir)
c := PluginConfig{}
err := c.Discover()
if err != nil {
t.Fatalf("error discovering plugins; %s", err.Error())
}
if c.Builders.Has("feather") {
t.Fatalf("expected to not find builder %q", "feather")
}
for mockPluginName, plugin := range tt.installedPluginsMock {
mockPluginName = strings.Split(mockPluginName, "_")[0]
for mockBuilderName := range plugin.Builders {
expectedBuilderName := mockPluginName + "-" + mockBuilderName
if c.Builders.Has(expectedBuilderName) {
t.Fatalf("expected to not find builder %q", expectedBuilderName)
}
}
for mockProvisionerName := range plugin.Provisioners {
expectedProvisionerName := mockPluginName + "-" + mockProvisionerName
if c.Provisioners.Has(expectedProvisionerName) {
t.Fatalf("expected to not find builder %q", expectedProvisionerName)
}
}
for mockPostProcessorName := range plugin.PostProcessors {
expectedPostProcessorName := mockPluginName + "-" + mockPostProcessorName
if c.PostProcessors.Has(expectedPostProcessorName) {
t.Fatalf("expected to not find post-processor %q", expectedPostProcessorName)
}
}
for mockDatasourceName := range plugin.Datasources {
expectedDatasourceName := mockPluginName + "-" + mockDatasourceName
if c.DataSources.Has(expectedDatasourceName) {
t.Fatalf("expected to not find datasource %q", expectedDatasourceName)
}
}
}
})
}
}
func Test_multiplugin_defaultName(t *testing.T) {
createMockPlugins(t, defaultNameMock)
pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
defer os.RemoveAll(pluginDir)
c := PluginConfig{}
err := c.Discover()
if err != nil {
t.Fatalf("error discovering plugins; %s ; mocks are %#v", err.Error(), defaultNameMock)
}
expectedBuilderNames := []string{"foo-bar", "foo-baz", "foo"}
for _, mockBuilderName := range expectedBuilderNames {
if !c.Builders.Has(mockBuilderName) {
t.Fatalf("expected to find builder %q; builders is %#v", mockBuilderName, c.Builders)
}
}
}
func Test_only_one_multiplugin_defaultName_each_plugin_type(t *testing.T) {
createMockPlugins(t, doubleDefaultMock)
pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
defer os.RemoveAll(pluginDir)
c := PluginConfig{}
err := c.Discover()
if err != nil {
t.Fatal("Should not have error because pluginsdk.DEFAULT_NAME is used twice but only once per plugin type.")
}
}

Loading…
Cancel
Save