Skip to content

client: disable deprecated NewClient() and NewEnvClient()#44019

Closed
thaJeztah wants to merge 1 commit intomoby:masterfrom
thaJeztah:client_complete_deprecation
Closed

client: disable deprecated NewClient() and NewEnvClient()#44019
thaJeztah wants to merge 1 commit intomoby:masterfrom
thaJeztah:client_complete_deprecation

Conversation

@thaJeztah
Copy link
Member

@thaJeztah thaJeztah commented Aug 23, 2022

The NewClient() and NewEnvClient() functions were deprecated in 18.03 in
commit 772edd0 (#36140), but they continued to be functional.

Searching public repositories on GitHub shows that there's quite some projects
that haven't updated their code to use the replacements.

This patch updates both functions to become non-functional (to enforce a compilation
failure), but extend the function's documentaiton with instructions on migrating to
their non-deprecated alternatives. This should hopefully assist projects to migrate
their code.

- Description for the changelog

- A picture of a cute animal (not mandatory but encouraged)

func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) {
return NewClientWithOpts(WithHost(host), WithVersion(version), WithHTTPClient(client), WithHTTPHeaders(httpHeaders))
return nil, errors.New("deprecated: use 'client.NewClientWithOpts(WithHost(host), WithVersion(version), WithHTTPClient(client), WithHTTPHeaders(httpHeaders))'")
}
Copy link
Member

@AkihiroSuda AkihiroSuda Aug 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error might be confusing when (accidentally) visible to end-users of downstream projects.

Can we just remove this function so that downstreams can detect the change on the compilation time?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point; it won't be a compile error.

What I tried to achieve is to make it something that cannot be ignored by project using the old code, but giving them enough guidance to fix it. Perhaps as an alternative, we could;

  • change the signature to be incompatible (causing a compile failure); removing all returns.
  • change the function's documentation to provide the instructions

Something like:

// NewClient initializes a new API client for the given host and API version.
// It uses the given http client as transport.
// It also initializes the custom http headers to add to each request.
//
// It won't send any version information if the version number is empty. It is
// highly recommended that you set a version or your client may break if the
// server is upgraded.
//
// This function is deprecated, and is no longer functional.
//
// If you're using this function, replace it with the code below to get
// the equivalent (non-deprecated) code to initialize a client with a
// fixed API version:
//
//    client.NewClientWithOpts(
//        WithHost(host),
//        WithVersion(version),
//        WithHTTPClient(client),
//        WithHTTPHeaders(httpHeaders),
//    )
//
// We recommend to enable API version negotiation, so that the client
// automatically negotiate the API version to use when connecting with the
// daemon. To enable API version negotiation, use the WithAPIVersionNegotiation()
// option instead of WithVersion(version):
//
//    client.NewClientWithOpts(
//        WithHost(host),
//        WithAPIVersionNegotiation(),
//        WithHTTPClient(client),
//        WithHTTPHeaders(httpHeaders),
//    )
//
// Deprecated: use NewClientWithOpts
func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) {}

// NewEnvClient initializes a new API client based on environment variables.
// See FromEnv for a list of support environment variables.
//
// This function is deprecated, and is no longer functional.
//
// If you're using this function, replace it with the code below to get
// the equivalent (non-deprecated) code:
//
//    client.NewClientWithOpts(FromEnv)
//
// We recommend to enable API version negotiation, so that the client
// automatically negotiate the API version to use when connecting with the
// daemon. To enable API version negotiation, add the WithAPIVersionNegotiation()
// option:
//
//    client.NewClientWithOpts(FromEnv, WithAPIVersionNegotiation())
//
// Deprecated: use NewClientWithOpts
func NewEnvClient() {}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just comment out the code without breaking the prototype and add deprecation document there?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I thought that having the stub would allow people to more easily find it back (at least, my usual approach is to have my IDE link to the right file) and to still have docs at pkg.go.dev, but perhaps just grep could work of course

@thaJeztah thaJeztah force-pushed the client_complete_deprecation branch from 27ef95c to 1ccbb0f Compare August 24, 2022 17:02
The `NewClient()` and `NewEnvClient()` functions were deprecated in 18.03 in
commit 772edd0, but they continued to be functional.

Searching public repositories on GitHub shows that there's quite some projects
that haven't updated their code to use the replacements.

This patch updates both functions to become non-functional (to enforce a compilation
failure), but extend the function's documentaiton with instructions on migrating to
their non-deprecated alternatives. This should hopefully assist projects to migrate
their code.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
@thaJeztah thaJeztah force-pushed the client_complete_deprecation branch from 1ccbb0f to 4e78954 Compare August 24, 2022 17:04
@thaJeztah
Copy link
Member Author

@AkihiroSuda updated with what I described above; let me know if you think this is a better approach.

@thaJeztah
Copy link
Member Author

@AkihiroSuda @corhere @cpuguy83 PTAL (happy to get feedback on the approach; mostly wanting to make the replacement discoverable)

Copy link
Contributor

@corhere corhere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels really heavy-handed, and for what? The maintenance burden is trivial so we're just punishing downstream users who have not yet inlined the bodies of the deprecated constructors into their projects. I vote we keep these deprecated functions around in all current and future releases of package github.com/docker/docker/client for compatibility and remove them in the next semver-major version (read: when the package gets a different import path once we finish the moby transition). I know, I've heard it all before that we don't follow semver and have a history of making breaking changes to client methods. Making breaking changes to individual method signatures is one thing, but the constructors are the entrypoints into the package! Nearly every module which imports the client will be calling one of the constructors. That is a lot of modules to break when they add some dependabot-happy dependency which transitively requires the bleeding-edge version of the client. We've been burned by Go module dependency hell many times already; where's the empathy for our own downstream users?

Downstream consumers might start to migrate away from the NewClient constructor in their own time if it was correctly marked as deprecated. Could we try fixing the docs first before resorting to forcing the change upon users by intentionally breaking their builds?

@cpuguy83
Copy link
Member

cpuguy83 commented Oct 4, 2022

In addition to @corhere's comments, I think creating runtime errors for this is not ideal and it would be better to error out at compile time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants