Search code examples
gogo-modulesprometheus-operator

go mod download won't download a single library; how to mod import a single library without manipulating entire vendor cache


(disclaimer: apologies for wrong words used in this description. I'm still getting acquainted with go)

My understanding is that go modules are pretty finicky so this question kind of spans a few topics related to go modules and the prometheus operator library I'm trying to download and import.

One huge requirement: I cannot do a mass go mod download/upgrade as downstream deps get upgraded in my vendor directory and all kinds of havoc happens in our code. I'm trying to avoid that. I just want to "install" this one library (and any necessary ancillaries) and be done with it.

All of that said, what is the proper way to using go mod (or another proper tool) to obtain "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1" that will not update all of my vendor libs? I just need to import the v1 api there to set and read servicemonitors in my clusters programmatically.

$ go mod download -x github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1
module github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1: not a known dependency

or

$ go get github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1
go: found github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1 in github.com/coreos/prometheus-operator v0.41.1

my imports

import (
    "context"
    "encoding/base64"
    "fmt"
    v1 "k8s.io/api/core/v1"
    "k8s.io/apimachinery/pkg/util/intstr"
    "strings"
    "text/template"
    "time"

    "github.com/google/uuid"

    coreosv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"
    "github.com/go-kit/kit/log"

    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

The actual code I'm using this library for looks like:

    // define service monitor object
    serviceMonitorObject := &coreosv1.ServiceMonitor{
        ObjectMeta: metav1.ObjectMeta{
            Name:      objectMetaDataName,
            // TODO: fix namespace
            Namespace: "monitoring",
            Labels:    labels,
        },
        Spec: coreosv1.ServiceMonitorSpec{
            Selector: metav1.LabelSelector{
                MatchLabels: labels,
            },
            NamespaceSelector: coreosv1.NamespaceSelector{
                MatchNames: []string{
                    "monitoring",
                },
            },
            Endpoints: []coreosv1.Endpoint{
                {
                    Port: "metrics",
                    Interval: "10s",
                    HonorLabels: true,
                },
            },
        },
    }

However, I cannot seem to just import the one library. Any suggestions or assistance would be greatly appreciated.

The error github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1 in github.com/coreos/prometheus-operator v0.41.1 suggests that maybe I just import github.com/coreos/prometheus-operator but when I do that, my servicemonitor definition fails.

EDIT

I rmed my go.{mod,sum} and vendor directory and git reset --hard my environment, which restored the vendor state to just before my work. I ran the following, but as you can see, the get appears to work, but there is no coreos directory in existence under /project/vendor/*/.

$ go get -x github.com/coreos/prometheus-operator/
# get https://proxy.golang.org/github.com/coreos/@v/list
# get https://proxy.golang.org/github.com/@v/list
# get https://proxy.golang.org/github.com/coreos/prometheus-operator/@v/list
# get https://proxy.golang.org/github.com/@v/list: 410 Gone (0.794s)
# get https://proxy.golang.org/github.com/coreos/@v/list: 410 Gone (0.886s)
# get https://proxy.golang.org/github.com/coreos/prometheus-operator/@v/list: 200 OK (0.897s)
go: github.com/coreos/prometheus-operator upgrade => v0.41.1
$ find vendor -name '*prometheus*'
vendor/github.com/go-kit/kit/metrics/prometheus
vendor/github.com/go-kit/kit/metrics/prometheus/prometheus.go
vendor/github.com/prometheus
vendor/github.com/prometheus/client_golang/prometheus

Reset my environment again. Performed the following:

$ go mod download -x github.com/coreos/prometheus-operator/...
warning: pattern "github.com/coreos/prometheus-operator/..." matched no module dependencies
$ go mod download -x github.com/coreos/prometheus-operator/
module github.com/coreos/prometheus-operator/: not a known dependency

According to documentation, the following should show all mods used (grep core added to get more brief output):

$ go list -m all | grep core
github.com/coreos/bbolt v1.3.2
github.com/coreos/etcd v3.3.10+incompatible
github.com/coreos/go-etcd v2.0.0+incompatible
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/coreos/go-semver v0.3.0
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f
github.com/coreos/prometheus-operator v0.41.1

Yet, I still cannot compile:

$ make -f build/Makefile generators ims-bin-darwin && ./ims-api --config_file=/var/tmp/jim-ims-api.yaml --kubeconfig $HOME/.kube/config --populate_demo_db=true --populate_demo_file hack/demo1.yaml --debug_logging --db_debug_logging
./build/generators/api.sh
Ensuring Bin Directory (./build/generators/../../bin) Exists...
Ensuring Destination Directory ( pkg/generated/api ) Exists...
Ensuring Destination Directory ( pkg/generated/kaas-api ) Exists...
Ensuring Swagger Asset Directory ( assets/generated/swagger ) Exists...
go: inconsistent vendoring in /Users/jimconn/projects/src/ims-api:
        github.com/go-kit/[email protected]: is explicitly required in go.mod, but vendor/modules.txt indicates github.com/go-kit/[email protected]
        github.com/golang/[email protected]: is explicitly required in go.mod, but vendor/modules.txt indicates github.com/golang/[email protected]
        github.com/grpc-ecosystem/[email protected]: is explicitly required in go.mod, but vendor/modules.txt indicates github.com/grpc-ecosystem/[email protected]
        github.com/pkg/[email protected]: is explicitly required in go.mod, but vendor/modules.txt indicates github.com/pkg/[email protected]
        github.com/prometheus/[email protected]: is explicitly required in go.mod, but vendor/modules.txt indicates github.com/prometheus/[email protected]
        golang.org/x/[email protected]: is explicitly required in go.mod, but vendor/modules.txt indicates golang.org/x/[email protected]
        google.golang.org/[email protected]: is explicitly required in go.mod, but vendor/modules.txt indicates google.golang.org/[email protected]
        google.golang.org/[email protected]: is explicitly required in go.mod, but vendor/modules.txt indicates google.golang.org/[email protected]
        gopkg.in/[email protected]: is explicitly required in go.mod, but vendor/modules.txt indicates gopkg.in/[email protected]
        k8s.io/[email protected]: is explicitly required in go.mod, but vendor/modules.txt indicates k8s.io/[email protected]
        k8s.io/[email protected]: is explicitly required in go.mod, but vendor/modules.txt indicates k8s.io/[email protected]
        k8s.io/[email protected]: is explicitly required in go.mod, but vendor/modules.txt indicates k8s.io/[email protected]

run 'go mod vendor' to sync, or use -mod=mod or -mod=readonly to ignore the vendor directory
make: *** [generators] Error 1

I ran go mod vendor and I'm back in this condition where my entire vendor tree is changed:

$ g st
On branch expose-bm-prom
Your branch is up to date with 'origin/expose-bm-prom'.

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   assets/generated/swagger/api.swagger.json
        modified:   go.mod
        modified:   go.sum
        modified:   pkg/generated/api/api.pb.go
        modified:   pkg/generated/api/api.pb.gw.go
...
        modified:   vendor/sigs.k8s.io/yaml/README.md
        modified:   vendor/sigs.k8s.io/yaml/yaml.go

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        vendor/github.com/cespare/
        vendor/github.com/coreos/
        vendor/github.com/golang/protobuf/internal/
        vendor/github.com/golang/protobuf/jsonpb/decode.go
        vendor/github.com/golang/protobuf/jsonpb/encode.go
...
        vendor/k8s.io/client-go/util/workqueue/
        vendor/sigs.k8s.io/structured-merge-diff/
        vendor/sigs.k8s.io/yaml/go.mod
        vendor/sigs.k8s.io/yaml/go.sum

no changes added to commit (use "git add" and/or "git commit -a")
$ g st | grep -c vendor
942    # files changed

Is this just the state of the world? Am I not able to import this library without dealing with a huge chunk of changes to the entire vendor tree, which completely breaks my code! This is ridiculous!


Solution

  • go get -d github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1 is the correct way to add a dependency on the latest version of the module that provides that package.

    When go get adds a module dependency, it upgrades other dependencies as needed in order to satisfy the requirements of the new module. That is probably why you are seeing a lot of changes when you run go mod vendor.

    If you want to minimize those changes, you may need to explicitly choose an older version (so that it will have older requirements):

    go get -d github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1@$OLD_VERSION