From 1032db4f9d651a35df009750478e0476e86d6ae2 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 25 Nov 2020 18:39:34 -0500 Subject: [PATCH] remove generate-plugins script and test We no longer use internal plugins. --- scripts/generate-plugins.go | 285 ------------------------------- scripts/generate-plugins_test.go | 99 ----------- 2 files changed, 384 deletions(-) delete mode 100644 scripts/generate-plugins.go delete mode 100644 scripts/generate-plugins_test.go diff --git a/scripts/generate-plugins.go b/scripts/generate-plugins.go deleted file mode 100644 index 24030bcf6..000000000 --- a/scripts/generate-plugins.go +++ /dev/null @@ -1,285 +0,0 @@ -// Generate Plugins is a small program that updates the lists of plugins in -// command/internal_plugin_list.go so they will be compiled into the main -// terraform binary. -package main - -import ( - "fmt" - "go/ast" - "go/parser" - "go/token" - "io/ioutil" - "log" - "os" - "path/filepath" - "sort" - "strings" -) - -const target = "command/internal_plugin_list.go" - -func main() { - if isProjectRoot() == false { - log.Fatalf("This program must be invoked in the terraform project root") - } - - //// Collect all of the data we need about plugins we have in the project - //providers, err := discoverProviders() - //if err != nil { - // log.Fatalf("Failed to discover providers: %s", err) - //} - - provisioners, err := discoverProvisioners() - if err != nil { - log.Fatalf("Failed to discover provisioners: %s", err) - } - - // Do some simple code generation and templating - output := source - output = strings.Replace(output, "IMPORTS", makeImports(nil, provisioners), 1) - //output = strings.Replace(output, "PROVIDERS", makeProviderMap(providers), 1) - output = strings.Replace(output, "PROVISIONERS", makeProvisionerMap(provisioners), 1) - - // TODO sort the lists of plugins so we are not subjected to random OS ordering of the plugin lists - - // Write our generated code to the command/plugin.go file - file, err := os.Create(target) - defer file.Close() - if err != nil { - log.Fatalf("Failed to open %s for writing: %s", target, err) - } - - _, err = file.WriteString(output) - if err != nil { - log.Fatalf("Failed writing to %s: %s", target, err) - } - - log.Printf("Generated %s", target) -} - -type plugin struct { - Package string // Package name from ast remoteexec - PluginName string // Path via deriveName() remote-exec - TypeName string // Type of plugin provisioner - Path string // Relative import path builtin/provisioners/remote-exec - ImportName string // See deriveImport() remoteexecprovisioner -} - -// makeProviderMap creates a map of providers like this: -// -// var InternalProviders = map[string]plugin.ProviderFunc{ -// "aws": aws.Provider, -// "azurerm": azurerm.Provider, -// "cloudflare": cloudflare.Provider, -func makeProviderMap(items []plugin) string { - output := "" - for _, item := range items { - output += fmt.Sprintf("\t\"%s\": %s.%s,\n", item.PluginName, item.ImportName, item.TypeName) - } - return output -} - -func isProjectRoot() bool { - _, err := os.Stat("go.mod") - if os.IsNotExist(err) { - return false - } - - return true -} - -// makeProvisionerMap creates a map of provisioners like this: -// -// "chef": chefprovisioner.Provisioner, -// "salt-masterless": saltmasterlessprovisioner.Provisioner, -// "file": fileprovisioner.Provisioner, -// "local-exec": localexecprovisioner.Provisioner, -// "remote-exec": remoteexecprovisioner.Provisioner, -// -func makeProvisionerMap(items []plugin) string { - output := "" - for _, item := range items { - output += fmt.Sprintf("\t\"%s\": %s.%s,\n", item.PluginName, item.ImportName, item.TypeName) - } - return output -} - -func makeImports(providers, provisioners []plugin) string { - plugins := []string{} - - for _, provider := range providers { - plugins = append(plugins, fmt.Sprintf("\t%s \"github.com/hashicorp/terraform/%s\"\n", provider.ImportName, filepath.ToSlash(provider.Path))) - } - - for _, provisioner := range provisioners { - plugins = append(plugins, fmt.Sprintf("\t%s \"github.com/hashicorp/terraform/%s\"\n", provisioner.ImportName, filepath.ToSlash(provisioner.Path))) - } - - // Make things pretty - sort.Strings(plugins) - - return strings.Join(plugins, "") -} - -// listDirectories recursively lists directories under the specified path -func listDirectories(path string) ([]string, error) { - names := []string{} - items, err := ioutil.ReadDir(path) - if err != nil { - return names, err - } - - for _, item := range items { - // We only want directories - if item.IsDir() { - if item.Name() == "testdata" { - continue - } - currentDir := filepath.Join(path, item.Name()) - names = append(names, currentDir) - - // Do some recursion - subNames, err := listDirectories(currentDir) - if err == nil { - names = append(names, subNames...) - } - } - } - - return names, nil -} - -// deriveName determines the name of the plugin relative to the specified root -// path. -func deriveName(root, full string) string { - short, _ := filepath.Rel(root, full) - bits := strings.Split(short, string(os.PathSeparator)) - return strings.Join(bits, "-") -} - -// deriveImport will build a unique import identifier based on packageName and -// the result of deriveName(). This is important for disambigutating between -// providers and provisioners that have the same name. This will be something -// like: -// -// remote-exec -> remoteexecprovisioner -// -// which is long, but is deterministic and unique. -func deriveImport(typeName, derivedName string) string { - return strings.Replace(derivedName, "-", "", -1) + strings.ToLower(typeName) -} - -// discoverTypesInPath searches for types of typeID in path using go's ast and -// returns a list of plugins it finds. -func discoverTypesInPath(path, typeID, typeName string) ([]plugin, error) { - pluginTypes := []plugin{} - - dirs, err := listDirectories(path) - if err != nil { - return pluginTypes, err - } - - for _, dir := range dirs { - fset := token.NewFileSet() - goPackages, err := parser.ParseDir(fset, dir, nil, parser.AllErrors) - if err != nil { - return pluginTypes, fmt.Errorf("Failed parsing directory %s: %s", dir, err) - } - - for _, goPackage := range goPackages { - ast.PackageExports(goPackage) - ast.Inspect(goPackage, func(n ast.Node) bool { - switch x := n.(type) { - case *ast.FuncDecl: - // If we get a function then we will check the function name - // against typeName and the function return type (Results) - // against typeID. - // - // There may be more than one return type but in the target - // case there should only be one. Also the return type is a - // ast.SelectorExpr which means we have multiple nodes. - // We'll read all of them as ast.Ident (identifier), join - // them via . to get a string like terraform.ResourceProvider - // and see if it matches our expected typeID - // - // This is somewhat verbose but prevents us from identifying - // the wrong types if the function name is amiguous or if - // there are other subfolders added later. - if x.Name.Name == typeName && len(x.Type.Results.List) == 1 { - node := x.Type.Results.List[0].Type - typeIdentifiers := []string{} - ast.Inspect(node, func(m ast.Node) bool { - switch y := m.(type) { - case *ast.Ident: - typeIdentifiers = append(typeIdentifiers, y.Name) - } - // We need all of the identifiers to join so we - // can't break early here. - return true - }) - if strings.Join(typeIdentifiers, ".") == typeID { - derivedName := deriveName(path, dir) - pluginTypes = append(pluginTypes, plugin{ - Package: goPackage.Name, - PluginName: derivedName, - ImportName: deriveImport(x.Name.Name, derivedName), - TypeName: x.Name.Name, - Path: dir, - }) - } - } - case *ast.TypeSpec: - // In the simpler case we will simply check whether the type - // declaration has the name we were looking for. - if x.Name.Name == typeID { - derivedName := deriveName(path, dir) - pluginTypes = append(pluginTypes, plugin{ - Package: goPackage.Name, - PluginName: derivedName, - ImportName: deriveImport(x.Name.Name, derivedName), - TypeName: x.Name.Name, - Path: dir, - }) - // The AST stops parsing when we return false. Once we - // find the symbol we want we can stop parsing. - return false - } - } - return true - }) - } - } - - return pluginTypes, nil -} - -func discoverProviders() ([]plugin, error) { - path := "./builtin/providers" - typeID := "terraform.ResourceProvider" - typeName := "Provider" - return discoverTypesInPath(path, typeID, typeName) -} - -func discoverProvisioners() ([]plugin, error) { - path := "./builtin/provisioners" - typeID := "terraform.ResourceProvisioner" - typeName := "Provisioner" - return discoverTypesInPath(path, typeID, typeName) -} - -const source = `// -// This file is automatically generated by scripts/generate-plugins.go -- Do not edit! -// -package command - -import ( -IMPORTS - "github.com/hashicorp/terraform/plugin" -) - -var InternalProviders = map[string]plugin.ProviderFunc{} - -var InternalProvisioners = map[string]plugin.ProvisionerFunc{ -PROVISIONERS -} -` diff --git a/scripts/generate-plugins_test.go b/scripts/generate-plugins_test.go deleted file mode 100644 index cba015b85..000000000 --- a/scripts/generate-plugins_test.go +++ /dev/null @@ -1,99 +0,0 @@ -package main - -import "testing" - -func TestMakeProvisionerMap(t *testing.T) { - p := makeProvisionerMap([]plugin{ - { - Package: "file", - PluginName: "file", - TypeName: "Provisioner", - Path: "builtin/provisioners/file", - ImportName: "fileprovisioner", - }, - { - Package: "localexec", - PluginName: "local-exec", - TypeName: "Provisioner", - Path: "builtin/provisioners/local-exec", - ImportName: "localexecprovisioner", - }, - { - Package: "remoteexec", - PluginName: "remote-exec", - TypeName: "Provisioner", - Path: "builtin/provisioners/remote-exec", - ImportName: "remoteexecprovisioner", - }, - }) - - expected := ` "file": fileprovisioner.Provisioner, - "local-exec": localexecprovisioner.Provisioner, - "remote-exec": remoteexecprovisioner.Provisioner, -` - - if p != expected { - t.Errorf("Provisioner output does not match expected format.\n -- Expected -- \n%s\n -- Found --\n%s\n", expected, p) - } -} - -func TestDeriveName(t *testing.T) { - actual := deriveName("builtin/provisioners", "builtin/provisioners/magic/remote-exec") - expected := "magic-remote-exec" - if actual != expected { - t.Errorf("Expected %s; found %s", expected, actual) - } -} - -func TestDeriveImport(t *testing.T) { - actual := deriveImport("provider", "magic-aws") - expected := "magicawsprovider" - if actual != expected { - t.Errorf("Expected %s; found %s", expected, actual) - } -} - -func contains(plugins []plugin, name string) bool { - for _, plugin := range plugins { - if plugin.PluginName == name { - return true - } - } - return false -} - -//func TestDiscoverTypesProviders(t *testing.T) { -// plugins, err := discoverTypesInPath("../builtin/providers", "terraform.ResourceProvider", "Provider") -// if err != nil { -// t.Fatalf(err.Error()) -// } -// // We're just going to spot-check, not do this exhaustively -// if !contains(plugins, "aws") { -// t.Errorf("Expected to find aws provider") -// } -// if !contains(plugins, "docker") { -// t.Errorf("Expected to find docker provider") -// } -// if !contains(plugins, "dnsimple") { -// t.Errorf("Expected to find dnsimple provider") -// } -// if !contains(plugins, "triton") { -// t.Errorf("Expected to find triton provider") -// } -// if contains(plugins, "file") { -// t.Errorf("Found unexpected provider file") -// } -//} - -func TestDiscoverTypesProvisioners(t *testing.T) { - plugins, err := discoverTypesInPath("../builtin/provisioners", "terraform.ResourceProvisioner", "Provisioner") - if err != nil { - t.Fatalf(err.Error()) - } - if !contains(plugins, "remote-exec") { - t.Errorf("Expected to find remote-exec provisioner") - } - if contains(plugins, "aws") { - t.Errorf("Found unexpected provisioner aws") - } -}