tools/find-pkg-importer: Tool to find what imports a Go package
Some checks are pending
build / Build for freebsd_386 (push) Waiting to run
build / Build for linux_386 (push) Waiting to run
build / Build for openbsd_386 (push) Waiting to run
build / Build for windows_386 (push) Waiting to run
build / Build for freebsd_amd64 (push) Waiting to run
build / Build for linux_amd64 (push) Waiting to run
build / Build for openbsd_amd64 (push) Waiting to run
build / Build for solaris_amd64 (push) Waiting to run
build / Build for windows_amd64 (push) Waiting to run
build / Build for freebsd_arm (push) Waiting to run
build / Build for linux_arm (push) Waiting to run
build / Build for linux_arm64 (push) Waiting to run
build / Build for darwin_amd64 (push) Waiting to run
build / Build for darwin_arm64 (push) Waiting to run
build / End-to-end Tests for linux_386 (push) Waiting to run
build / End-to-end Tests for windows_386 (push) Waiting to run
build / End-to-end Tests for darwin_amd64 (push) Waiting to run
build / End-to-end Tests for linux_amd64 (push) Waiting to run
build / End-to-end Tests for windows_amd64 (push) Waiting to run
Quick Checks / List files changed for pull request (push) Waiting to run
Quick Checks / Unit tests for linux_386 (push) Blocked by required conditions
Quick Checks / Unit tests for linux_amd64 (push) Blocked by required conditions
Quick Checks / Unit tests for windows_amd64 (push) Blocked by required conditions
Quick Checks / Unit tests for linux_arm (push) Blocked by required conditions
Quick Checks / Unit tests for darwin_arm64 (push) Blocked by required conditions
Quick Checks / Unit tests for linux_arm64 (push) Blocked by required conditions
Quick Checks / Race Tests (push) Blocked by required conditions
Quick Checks / End-to-end Tests (push) Blocked by required conditions
Quick Checks / Code Consistency Checks (push) Blocked by required conditions
Quick Checks / License Checks (push) Waiting to run
Website checks / List files changed for pull request (push) Waiting to run
Website checks / Build (push) Blocked by required conditions
Website checks / Test Installation Instructions (push) Blocked by required conditions

Advisories in the Go vulnerability database often identify specific Go
packages or even specific symbols within Go packages that the advisory
applies to.

Therefore when we are evaluating the impact of an advisory on OpenTofu we
often need to ask the question "what parts of OpenTofu are using that
affected package?"

This new tool is a small wrapper around the "go list" command which takes
a package path of interest and returns all of the packages in OpenTofu's
package import graph that directly import the given package. The results
can include both OpenTofu's own packages and packages from upstream modules
or the Go standard library.

Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This commit is contained in:
Martin Atkins 2026-04-13 10:14:17 -07:00
parent b0339b83cf
commit ffb64bbd16
2 changed files with 83 additions and 0 deletions

1
go.mod
View file

@ -312,6 +312,7 @@ tool (
github.com/mitchellh/gox
github.com/opentofu/opentofu/cmd/tofu
github.com/opentofu/opentofu/tools/find-dep-upgrades
github.com/opentofu/opentofu/tools/find-pkg-importer
github.com/opentofu/opentofu/tools/loggraphdiff
github.com/opentofu/opentofu/tools/protobuf-compile
github.com/opentofu/opentofu/tools/selected-go-version

View file

@ -0,0 +1,82 @@
// Copyright (c) The OpenTofu Authors
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) 2023 HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
// find-pkg-importer is a utility for finding which packages in our dependency
// graph import a given package path.
//
// Run this from the root of your work tree for the OpenTofu repository so
// that it can find the project's "go.mod" file in the current working
// directory. For example, to find which packages import "html/template":
//
// go tool find-pkg-importer html/template
//
// Note that this tool deals in individual packages rather than whole modules,
// so that we can use it to evaluate our exposure to advisories from the Go
// vulnerability database which describes specific packages and symbols that
// are affected. Use "go mod graph" or "go mod why" to answer similar questions
// about entire modules.
package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"os"
"os/exec"
"slices"
)
func main() {
// We don't have any options, but this'll report an error if someone tries to use one
flag.Usage = func() {
fmt.Fprintln(os.Stderr, "Usage: go tool find-pkg-importer <PACKAGE-PATH>")
}
flag.Parse()
if len(os.Args) != 2 {
flag.Usage()
os.Exit(1)
}
wantPkg := os.Args[1]
cmd := exec.Command("go", "list", "-json=ImportPath,Imports", "all")
out, err := cmd.StdoutPipe()
if err != nil {
fatalf("Can't open pipe for child process stdout: %s", out)
}
dec := json.NewDecoder(out)
err = cmd.Start()
if err != nil {
fatalf("Failed to run 'go list': %s", err)
}
defer func() {
// Error intentionally ignored becuse there's nothing useful we could
// do about it anyway.
_ = cmd.Wait()
}()
type Candidate struct {
ImportPath string `json:"ImportPath"`
Imports []string `json:"Imports"`
}
for {
var candidate Candidate
err := dec.Decode(&candidate)
if err == io.EOF {
break
}
if err != nil {
fatalf("Failed to parse record from 'go list': %s", err)
}
if slices.Contains(candidate.Imports, wantPkg) {
fmt.Println(candidate.ImportPath)
}
}
}
func fatalf(format string, a ...any) {
fmt.Fprintf(os.Stderr, format+"\n", a...)
os.Exit(1)
}