21

Is there a way to pin docker API version using the golang client? (short of using dep for vendoring)

code below fails with

client version 1.38 is too new. Maximum supported API version is 1.37

This code ran fine until recently

go version go1.9.5 linux/amd64

here is : docker version

Client:
 Version:      18.05.0-ce
 API version:  1.37
 Go version:   go1.9.5
 Git commit:   f150324
 Built:        Wed May  9 22:16:25 2018
 OS/Arch:      linux/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.05.0-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.5
  Git commit:   f150324
  Built:        Wed May  9 22:14:32 2018
  OS/Arch:      linux/amd64
  Experimental: false

this kicks up the API version mismatch

package main

// kill off some containers

import (
    "fmt"

    "github.com/docker/docker/api/types"
    "github.com/docker/docker/client"
    "golang.org/x/net/context"

    "strings"
)

func main() {
    ctx := context.Background()
    cli, err := client.NewEnvClient()
    if err != nil {
        panic(err) // <--- crashes here due to API mismatch
    }

    containers, err := cli.ContainerList(ctx, types.ContainerListOptions{})
    if err != nil {
        panic(err)
    }

    for _, container := range containers {

        if strings.Contains(container.Image, "enduser") || strings.Contains(container.Image, "admin") {

            fmt.Println("\n we found enduser or admin so lets stop it\n")

            fmt.Print("Stopping container ", container.ID[:10], "... ")
            if err := cli.ContainerStop(ctx, container.ID, nil); err != nil {
                panic(err)
            }
            fmt.Println("Success")
        }
    }
}

In English, the above error is because the default client version of the github repo client library is newer than version supported by Docker ... so to address the comment - one approach which works is to request a lower version of the repo library to match Docker, not to request a higher version

Below approach to negotiate also works fine

cli, err := client.NewClientWithOpts(client.WithAPIVersionNegotiation())

Scott Stensland
  • 26,870
  • 12
  • 93
  • 104
  • 1
    Just ran into the same issue: `client version 1.40 is too new. Maximum supported API version is 1.39.` It doesn't make sense to me to set the client version to something higher than the currently supported API version (1.39 as of now): https://docs.docker.com/develop/sdk/. – kev Jan 30 '19 at 23:47

3 Answers3

32

You can ask for a version specifically with NewClientWithOpts().

package main

import (
    "net/http"

    "github.com/docker/docker/api/types/container"
    "github.com/docker/docker/client"
    "golang.org/x/net/context"
)

func main() {
    ctx := context.Background()
    cli, err := client.NewClientWithOpts(client.WithVersion("1.37"))
    if err != nil {
        panic(err)
    }
}

See Versioned API and SDK. At the tail end it brings up using the Go API and (tries) to link to the relevant code:

You can specify the API version to use, in one of the following ways:

The docs hard link to a line number on the master branch which has probably changed, but the code above should provide you with enough context to understand.

zero298
  • 25,467
  • 10
  • 75
  • 100
13

I had the exact same problem and @zero298's answer worked perfectly for me =)

Then I found client.WithAPIVersionNegotiation() and that also worked!

If you don't require pinning the version and just want the code to work with whatever version your machine is running, I think this option will suite your needs.

Henry Blyth
  • 1,700
  • 1
  • 15
  • 23
2
ctx := context.Background()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
   panic(err)
}
cli.NegotiateAPIVersion(ctx)  // this line can negotiate API version

NegotiateAPIVersion of client method can solve this API version mismatch problem.

yadda
  • 177
  • 2
  • 12