<p>We are using <a href="https://github.com/kubeflow/kfserving/tree/v0.5.1" rel="nofollow noreferrer">KFServing</a> in our kubernetes cluster. The project provides InferenceService struct and clientset in the folder pkg/.</p>
<p>How to import these packages under <a href="https://github.com/kubeflow/kfserving/tree/v0.5.1/pkg/client" rel="nofollow noreferrer">pkg/client</a>? My code is as below:</p>
<pre><code>package main
import (
    &quot;fmt&quot;
    kfs 
   &quot;github.com/kubeflow/kfserving/pkg/client/clientset/versioned&quot;
)

func main() {
   var clientset   *kfs.Cientset
   clientset = kfs.NewForConfig(nil)
   fmt.Println(clientset)
}
           
</code></pre>
<p>Try <em><strong>go mod tidy</strong></em> i got (I need dev on specified version v0.5.1):</p>
<pre><code>    main imports
    github.com/kubeflow/kfserving/pkg/client/clientset/versioned 
    imports
    k8s.io/client-go/discovery imports
    github.com/googleapis/gnostic/OpenAPIv2: 
     module github.com/googleapis/gnostic@latest found (v0.5.5), 
     but does not contain package 
     github.com/googleapis/gnostic/OpenAPIv2
     main imports
    github.com/kubeflow/kfserving/pkg/client/clientset/versioned 
    imports
    ...
</code></pre>
<p>Try compiling these code i got:</p>
<pre><code>  a lot of errors .....
</code></pre>
<p>After <em><strong>go get github.com/kubeflow/kfserving</strong></em> I got:</p>
<p>Then I changed the go.mod and reconfiged the kfseving version from v0.6.0 to v0.5.1 and then recompile these code, still got below error:</p>
<pre><code>go build .
 go: github.com/kubeflow/kfserving@v0.5.1: missing go.sum entry; to add it:
    go mod download github.com/kubeflow/kfserving
</code></pre>
<p>contens of go.mod:</p>
<pre><code>module main

go 1.16

require github.com/kubeflow/kfserving v0.5.1 // indirect
</code></pre>
<p><strong>UPDATE</strong><br />
<strong>for kfserving v0.4.0 everything works well</strong></p>

Wallace
<p>Looking at the <code>kfserving</code> <code>go.mod</code> file at <code>v0.5.1</code>, I see <a href="https://github.com/kubeflow/kfserving/blob/aa1042a3b6f72a65f16e13771ce335b1844ad7fc/go.mod#L46-L71" rel="nofollow noreferrer">a big block of <code>replace</code> directives</a>. By design, <a href="https://golang.org/ref/mod#go-mod-file-replace" rel="nofollow noreferrer"><code>replace</code> directives</a> “only apply in the main module's <code>go.mod</code> file and are ignored in other modules”, so it looks like <code>kfserving</code> has some technical debt here that they're passing on to you.</p>
<p>I started with an empty <code>go.mod</code> file and pasted in those <code>replace</code> directives. Then:</p>
<pre><code>$ go get -d github.com/kubeflow/kfserving/pkg/client/clientset/versioned@v0.5.1
go get: added github.com/PuerkitoBio/purell v1.1.1
…
go get: added sigs.k8s.io/yaml v1.2.0
</code></pre>
<p>The <code>.go</code> source file needed a few fixes for typos and mismatched types. I fudged it to:</p>
<pre class="lang-golang prettyprint-override"><code>package main

import (
    &quot;fmt&quot;

    kfs &quot;github.com/kubeflow/kfserving/pkg/client/clientset/versioned&quot;
)

func main() {
    var clientset *kfs.Clientset
    clientset = kfs.NewForConfigOrDie(nil)
    fmt.Println(clientset)
}
</code></pre>
<p>and then <code>go build .</code> succeeds:</p>
<pre><code>$ go build -o /dev/null .
</code></pre>
<p>Now I'll run <code>go mod tidy</code> to clean up the <code>go.mod</code> and <code>go.sum</code> files:</p>
<pre><code>$ go mod tidy
go: downloading github.com/stretchr/testify v1.5.1
…
go: downloading github.com/jmespath/go-jmespath v0.3.0
</code></pre>
<hr />
<p>But wait! I've still got all of the technical debt from <code>kfserving/go.mod</code> — without any comments explaining the choice of versions! — and I'm passing that technical debt on to any downstream users. Let's see if I can improve the situation while I'm here.</p>
<p>Go 1.16 handles the <code>exclude</code> directive a lot better than previous Go versions did, so maybe I can use a couple of targeted <code>exclude</code> directives instead of the (rather large) <code>replace</code> hammer.</p>
<p>I'll start by committing the fixes so far. (If nothing else, I want to be able to <code>git diff</code> the requirements to see what has changed.)</p>
<pre><code>$ git add *.go go.mod go.sum

$ git commit -m 'fixed kfserving build'
[main fd93b1d] fixed kfserving build
 3 files changed, 1643 insertions(+), 2 deletions(-)
 create mode 100644 go.sum
</code></pre>
<p>I notice that all of the <code>replace</code> directives apply to <code>k8s.io</code> paths, so I'll list the current versions of those paths to see what needs to be fixed:</p>
<pre><code>$ go list -m k8s.io/...
k8s.io/api v0.19.2 =&gt; k8s.io/api v0.19.2
k8s.io/apiextensions-apiserver v0.19.2 =&gt; k8s.io/apiextensions-apiserver v0.19.2
k8s.io/apimachinery v0.19.2 =&gt; k8s.io/apimachinery v0.19.2
k8s.io/apiserver v0.19.2 =&gt; k8s.io/apiserver v0.19.2
k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible =&gt; k8s.io/client-go v0.19.2
k8s.io/cloud-provider v0.19.2 =&gt; k8s.io/cloud-provider v0.19.2
k8s.io/code-generator v0.19.2 =&gt; k8s.io/code-generator v0.19.2
k8s.io/component-base v0.19.2 =&gt; k8s.io/component-base v0.19.2
k8s.io/csi-translation-lib v0.19.2 =&gt; k8s.io/csi-translation-lib v0.19.2
k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14
k8s.io/klog v1.0.0 =&gt; k8s.io/klog v1.0.0
k8s.io/klog/v2 v2.2.0
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6
k8s.io/legacy-cloud-providers v0.17.4 =&gt; k8s.io/legacy-cloud-providers v0.19.2
k8s.io/test-infra v0.0.0-20200803112140-d8aa4e063646 =&gt; k8s.io/test-infra v0.0.0-20200803112140-d8aa4e063646
k8s.io/utils v0.0.0-20200912215256-4140de9c8800 =&gt; k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89
</code></pre>
<p>Most of those look fine, but there are three mismatched versions:</p>
<pre><code>k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible =&gt; k8s.io/client-go v0.19.2
…
k8s.io/legacy-cloud-providers v0.17.4 =&gt; k8s.io/legacy-cloud-providers v0.19.2
…
k8s.io/utils v0.0.0-20200912215256-4140de9c8800 =&gt; k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89
</code></pre>
<p><code>legacy-cloud-providers</code> just needs an upgrade, so that should be easy enough to fix with <code>go get</code> — but it's not relevant to this package anyway so I can just let it float to whatever version it ends up at. I'll cut down the <code>replace</code> directives to just the two remaining modules and see how far I get:</p>
<pre><code>replace (
    k8s.io/client-go =&gt; k8s.io/client-go v0.19.2
    k8s.io/utils =&gt; k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89
)
</code></pre>
<p>Now:</p>
<pre><code>$ go mod tidy

$ go build -o /dev/null .
</code></pre>
<p>Ok, so the build is still good — I've made incremental progress, so I'll lock that in:</p>
<pre><code>$ git add go.mod go.sum

$ git commit -m 'go.mod: remove irrelevant replacements'
[main cdbc1db] go.mod: remove irrelevant replacements
 3 files changed, 456 insertions(+), 43 deletions(-)
 rewrite go.mod (85%)
 create mode 100755 m
</code></pre>
<p>Now let's try notching out the bad <code>client-go</code> versions with <code>exclude</code> directives:</p>
<pre><code>$ go mod edit -exclude=k8s.io/client-go@v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible

$ go list -m k8s.io/client-go
k8s.io/client-go v9.0.0+incompatible =&gt; k8s.io/client-go v0.19.2

$ go mod edit -exclude=k8s.io/client-go@v9.0.0+incompatible

$ go list -m k8s.io/client-go
k8s.io/client-go v0.19.2 =&gt; k8s.io/client-go v0.19.2
</code></pre>
<p>Now I'm at the <code>client-go</code> version I needed, so I can drop that <code>replace</code> directive:</p>
<pre><code>$ go mod edit -dropreplace=k8s.io/client-go

$ go mod tidy

$ go build -o /dev/null .
</code></pre>
<p>And again lock it in:</p>
<pre><code>$ git add go.mod go.sum

$ git commit -m 'go.mod: use exclude instead of replace to notch out unwanted client-go versions'
[main de69965] go.mod: use exclude instead of replace to notch out unwanted client-go versions
 2 files changed, 21 insertions(+), 3 deletions(-)
</code></pre>
<p>Now let's see what's going on with this <code>k8s.io/utils</code> replacement. I suspect that it isn't really needed — the version will be upgraded a bit, but I'm betting it won't break the build. And, indeed, it seems to be fine:</p>
<pre><code>$ go list -m k8s.io/utils
k8s.io/utils v0.0.0-20200912215256-4140de9c8800 =&gt; k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89

$ go mod edit -dropreplace=k8s.io/utils

$ go mod tidy

$ go build -o /dev/null .

$ go list -m k8s.io/utils
k8s.io/utils v0.0.0-20200912215256-4140de9c8800
</code></pre>
<hr />
<p>So now I've successfully reduced that big nest of <code>replace</code> directives from <code>kfserving</code> to just a couple of <code>exclude</code> directives targeted retracted versions of <code>k8s.io/client-go</code>. Here's my whole <code>go.mod</code> file at the end of this process:</p>
<pre><code>module example.com/m

go 1.16

exclude (
    k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible
    k8s.io/client-go v9.0.0+incompatible
)

require github.com/kubeflow/kfserving v0.5.1
</code></pre>
