From a5fff9a5d09422cb8632777d797b809595374b87 Mon Sep 17 00:00:00 2001 From: Jordan Liggitt Date: Wed, 2 Aug 2023 15:44:25 -0400 Subject: [PATCH] Catch direct references to unwanted dependencies in kubernetes modules --- cmd/dependencyverifier/dependencyverifier.go | 39 ++++++++++++++------ hack/unwanted-dependencies.json | 20 +++++++++- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/cmd/dependencyverifier/dependencyverifier.go b/cmd/dependencyverifier/dependencyverifier.go index 24fe01fd8fd..54df5053f50 100644 --- a/cmd/dependencyverifier/dependencyverifier.go +++ b/cmd/dependencyverifier/dependencyverifier.go @@ -50,7 +50,13 @@ type UnwantedStatus struct { // runCommand runs the cmd and returns the combined stdout and stderr, or an // error if the command failed. func runCommand(cmd ...string) (string, error) { - output, err := exec.Command(cmd[0], cmd[1:]...).CombinedOutput() + return runCommandInDir("", cmd) +} + +func runCommandInDir(dir string, cmd []string) (string, error) { + c := exec.Command(cmd[0], cmd[1:]...) + c.Dir = dir + output, err := c.CombinedOutput() if err != nil { return "", fmt.Errorf("failed to run %q: %s (%s)", strings.Join(cmd, " "), err, output) } @@ -155,8 +161,6 @@ func parseModule(s string) module { // option1: dependencyverifier dependencies.json // it will run `go mod graph` and check it. -// option2: dependencyverifier dependencies.json mod.graph -// it will check the specified mod graph result file. func main() { var modeGraphStr string var err error @@ -166,15 +170,8 @@ func main() { if err != nil { log.Fatalf("Error running 'go mod graph': %s", err) } - } else if len(os.Args) == 3 { - modGraphFile := string(os.Args[2]) - modeGraphStr, err = readFile(modGraphFile) - // read file, such as `mod.graph` - if err != nil { - log.Fatalf("Error reading mod file %s: %s", modGraphFile, err) - } } else { - log.Fatalf("Usage: %s dependencies.json {mod.graph}", os.Args[0]) + log.Fatalf("Usage: %s dependencies.json", os.Args[0]) } dependenciesJSONPath := string(os.Args[1]) @@ -194,6 +191,22 @@ func main() { // convert from `go mod graph` to main module and map of from->[]to references mainModules, moduleGraph := convertToMap(modeGraphStr) + directDependencies := map[string]map[string]bool{} + for _, mainModule := range mainModules { + dir := "" + if mainModule.name != "k8s.io/kubernetes" { + dir = "staging/src/" + mainModule.name + } + listOutput, err := runCommandInDir(dir, []string{"go", "list", "-m", "-f", "{{if not .Indirect}}{{if not .Main}}{{.Path}}{{end}}{{end}}", "all"}) + if err != nil { + log.Fatalf("Error running 'go list' for %s: %s", mainModule.name, err) + } + directDependencies[mainModule.name] = map[string]bool{} + for _, directDependency := range strings.Split(listOutput, "\n") { + directDependencies[mainModule.name][directDependency] = true + } + } + // gather the effective versions by looking at the versions required by the main modules effectiveVersions := map[string]module{} for _, mainModule := range mainModules { @@ -253,6 +266,8 @@ func main() { // record specific names of versioned referents if referencer.version != "" && referencer.version != "v0.0.0" { config.Status.UnwantedReferences[unwanted] = append(config.Status.UnwantedReferences[unwanted], referencer.name) + } else if directDependencies[referencer.name][unwanted] { + config.Status.UnwantedReferences[unwanted] = append(config.Status.UnwantedReferences[unwanted], referencer.name) } } } @@ -271,7 +286,7 @@ func main() { if !bytes.Equal(expected, actual) { log.Printf("Expected status of\n%s", string(expected)) log.Printf("Got status of\n%s", string(actual)) - log.Fatal("Status diff:\n", cmp.Diff(actual, expected)) + log.Fatal("Status diff:\n", cmp.Diff(expected, actual)) } for expectedRef, expectedFrom := range configFromFile.Status.UnwantedReferences { actualFrom, ok := config.Status.UnwantedReferences[expectedRef] diff --git a/hack/unwanted-dependencies.json b/hack/unwanted-dependencies.json index c2fa00a8502..851af478b83 100644 --- a/hack/unwanted-dependencies.json +++ b/hack/unwanted-dependencies.json @@ -104,7 +104,19 @@ "go.etcd.io/etcd/api/v3", "go.etcd.io/etcd/client/v3", "go.etcd.io/etcd/raft/v3", - "go.etcd.io/etcd/server/v3" + "go.etcd.io/etcd/server/v3", + "k8s.io/api", + "k8s.io/apiextensions-apiserver", + "k8s.io/apimachinery", + "k8s.io/apiserver", + "k8s.io/client-go", + "k8s.io/code-generator", + "k8s.io/cri-api", + "k8s.io/kms", + "k8s.io/kube-aggregator", + "k8s.io/kubelet", + "k8s.io/kubernetes", + "k8s.io/metrics" ], "github.com/google/shlex": [ "sigs.k8s.io/kustomize/api", @@ -149,6 +161,8 @@ "github.com/grpc-ecosystem/go-grpc-middleware", "go.uber.org/zap", "gotest.tools/v3", + "k8s.io/kubectl", + "k8s.io/kubernetes", "k8s.io/system-validators", "sigs.k8s.io/kustomize/api", "sigs.k8s.io/kustomize/kustomize/v5" @@ -163,7 +177,9 @@ "cloud.google.com/go/compute", "cloud.google.com/go/storage", "github.com/GoogleCloudPlatform/k8s-cloud-provider", - "github.com/googleapis/gax-go/v2" + "github.com/googleapis/gax-go/v2", + "k8s.io/kubernetes", + "k8s.io/legacy-cloud-providers" ], "google.golang.org/genproto": [ "cloud.google.com/go",