From 72cea7c09a9c6d4eda9712c986981ea9122a9889 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Tue, 21 Jul 2026 18:45:02 -0400 Subject: [PATCH 1/3] Upgrade linodego and Docker Machine --- go.mod | 23 ++++++------ go.sum | 46 +++++++++++------------ pkg/drivers/linode/linode.go | 73 ++++++++++++++++++++++++++---------- 3 files changed, 86 insertions(+), 56 deletions(-) diff --git a/go.mod b/go.mod index 65436d0..f730bd0 100644 --- a/go.mod +++ b/go.mod @@ -1,30 +1,29 @@ module github.com/linode/docker-machine-driver-linode -go 1.25.0 +go 1.25.8 // This replacement is necessary to support Docker versions > v20.x.x // which provide critical security fixes. -replace github.com/docker/machine => gitlab.com/gitlab-org/ci-cd/docker-machine v0.16.2-gitlab.43 +replace github.com/docker/machine => gitlab.com/gitlab-org/ci-cd/docker-machine v0.16.2-gitlab.46 require ( github.com/docker/machine v0.16.2 github.com/google/go-cmp v0.7.0 - github.com/linode/linodego v1.69.1 + github.com/linode/linodego/v2 v2.4.2 github.com/stretchr/testify v1.11.1 golang.org/x/oauth2 v0.36.0 ) require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-resty/resty/v2 v2.17.2 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/google/go-querystring v1.2.0 // indirect github.com/kr/text v0.2.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/crypto v0.51.0 // indirect - golang.org/x/net v0.54.0 // indirect - golang.org/x/sys v0.44.0 // indirect - golang.org/x/term v0.43.0 // indirect - golang.org/x/text v0.37.0 // indirect - gopkg.in/ini.v1 v1.67.2 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + golang.org/x/crypto v0.53.0 // indirect + golang.org/x/net v0.56.0 // indirect + golang.org/x/sys v0.46.0 // indirect + golang.org/x/term v0.44.0 // indirect + golang.org/x/text v0.40.0 // indirect + gopkg.in/ini.v1 v1.67.3 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index cd784df..475866d 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-resty/resty/v2 v2.17.2 h1:FQW5oHYcIlkCNrMD2lloGScxcHJ0gkjshV3qcQAyHQk= -github.com/go-resty/resty/v2 v2.17.2/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2mLtQrOyQlVA= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= @@ -15,12 +14,13 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/linode/linodego v1.69.1 h1:f45N2MHR/oece2/ktTTCYmrlfse4//k3NgwcF5zbGZ0= -github.com/linode/linodego v1.69.1/go.mod h1:Fha0NYsQSx5VZK1HQNJY/z/dIxxkFp+vb5veawbmAUw= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/linode/linodego/v2 v2.4.2 h1:hOgnvX2IywFz3L1OXND08UP4D/90kmTSEreMMQkHZuQ= +github.com/linode/linodego/v2 v2.4.2/go.mod h1:LRzvYK/LFaGNqFmDxg1fZBtrolZOPvIdX9bssjwy5BA= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -30,27 +30,25 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -gitlab.com/gitlab-org/ci-cd/docker-machine v0.16.2-gitlab.43 h1:3AOpTvIZHfvNnCEaPvmMTiX65gY3yYtpabcAZJUgsTE= -gitlab.com/gitlab-org/ci-cd/docker-machine v0.16.2-gitlab.43/go.mod h1:WDpNHYkfs5yjw3iwSBFrFrsGZRGf2hPjkLVCbCvJvj8= -golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= -golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= -golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= -golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= +gitlab.com/gitlab-org/ci-cd/docker-machine v0.16.2-gitlab.46 h1:Pb99y+m41TyisYAuQUnDyU58Wjopw5jJs1iEFSBDmEw= +gitlab.com/gitlab-org/ci-cd/docker-machine v0.16.2-gitlab.46/go.mod h1:gtOdjxEWrDTXEkJA9bnG1nU/0+SUZuCZzQtN7CfJsqU= +golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= +golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= -golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= -golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= -golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= -golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= -golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= -golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= -golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= +golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y= +golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= +golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/ini.v1 v1.67.2 h1:JtOSMb9OuaCZKr7h5D/h6iii14sK0hLbplTc6frx4Ss= -gopkg.in/ini.v1 v1.67.2/go.mod h1:x/cyOwCgZqOkJoDIJ3c1KNHMo10+nLGAhh+kn3Zizss= +gopkg.in/ini.v1 v1.67.3 h1:iM9Lhz5MRSGhHVGGwCuzG9KO8PoirCXj/m/qTmOJJQw= +gopkg.in/ini.v1 v1.67.3/go.mod h1:x/cyOwCgZqOkJoDIJ3c1KNHMo10+nLGAhh+kn3Zizss= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/drivers/linode/linode.go b/pkg/drivers/linode/linode.go index 096c6df..0341d7f 100644 --- a/pkg/drivers/linode/linode.go +++ b/pkg/drivers/linode/linode.go @@ -13,13 +13,14 @@ import ( "regexp" "strconv" "strings" + "time" "github.com/docker/machine/libmachine/drivers" "github.com/docker/machine/libmachine/log" "github.com/docker/machine/libmachine/mcnflag" "github.com/docker/machine/libmachine/ssh" "github.com/docker/machine/libmachine/state" - "github.com/linode/linodego" + "github.com/linode/linodego/v2" "golang.org/x/oauth2" ) @@ -84,7 +85,7 @@ func NewDriver(hostName, storePath string) *Driver { } // getClient prepares the Linode APIv4 Client -func (d *Driver) getClient() *linodego.Client { +func (d *Driver) getClient() (*linodego.Client, error) { if d.client == nil { tokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: d.APIToken}) @@ -96,7 +97,10 @@ func (d *Driver) getClient() *linodego.Client { ua := fmt.Sprintf("docker-machine-driver-%s/%s", d.DriverName(), VERSION) - client := linodego.NewClient(oauth2Client) + client, err := linodego.NewClient(oauth2Client) + if err != nil { + return nil, err + } if len(d.UserAgentPrefix) > 0 { ua = fmt.Sprintf("%s %s", d.UserAgentPrefix, ua) } @@ -104,7 +108,7 @@ func (d *Driver) getClient() *linodego.Client { client.SetUserAgent(ua) d.client = &client } - return d.client + return d.client, nil } // SetClient sets the Linode API client for the driver @@ -328,11 +332,13 @@ func (d *Driver) PreCreateCheck() error { // TODO(displague) linode-stackscript-file should be read and uploaded (private), then used for boot. // RevNote could be sha256 of file so the file can be referenced instead of reuploaded. - client := d.getClient() + client, err := d.getClient() + if err != nil { + return err + } if d.RootPassword == "" { log.Info("Generating a secure disposable linode-root-pass...") - var err error d.RootPassword, err = createRandomRootPassword() if err != nil { return err @@ -396,7 +402,10 @@ func (d *Driver) Create() error { return err } - client := d.getClient() + client, err := d.getClient() + if err != nil { + return err + } boolBooted := !d.CreatePrivateIP // Create a linode @@ -438,7 +447,7 @@ func (d *Driver) Create() error { d.Region = linode.Region for _, address := range linode.IPv4 { - if private := privateIP(*address); !private { + if private := privateIP(address); !private { d.IPAddress = address.String() } else if d.CreatePrivateIP { d.PrivateIPAddress = address.String() @@ -480,13 +489,17 @@ func (d *Driver) Create() error { return err } - if err := client.BootInstance(context.TODO(), linode.ID, configs[0].ID); err != nil { + if err := client.BootInstance(context.TODO(), linode.ID, linodego.InstanceBootOptions{ + ConfigID: &configs[0].ID, + }); err != nil { return err } } log.Info("Waiting for Machine Running...") - if _, err := client.WaitForInstanceStatus(context.TODO(), d.InstanceID, linodego.InstanceRunning, 180); err != nil { + waitContext, cancel := context.WithTimeout(context.Background(), 180*time.Second) + defer cancel() + if _, err := client.WaitForInstanceStatus(waitContext, d.InstanceID, linodego.InstanceRunning); err != nil { return fmt.Errorf("wait for machine running failed: %s", err) } @@ -509,7 +522,12 @@ func (d *Driver) GetURL() (string, error) { // GetState returns the state that the host is in (running, stopped, etc) func (d *Driver) GetState() (state.State, error) { - linode, err := d.getClient().GetInstance(context.TODO(), d.InstanceID) + client, err := d.getClient() + if err != nil { + return state.Error, err + } + + linode, err := client.GetInstance(context.TODO(), d.InstanceID) if err != nil { return state.Error, err } @@ -539,20 +557,29 @@ func (d *Driver) GetState() (state.State, error) { // Start a host func (d *Driver) Start() error { log.Debug("Start...") - err := d.getClient().BootInstance(context.TODO(), d.InstanceID, 0) - return err + client, err := d.getClient() + if err != nil { + return err + } + return client.BootInstance(context.TODO(), d.InstanceID, linodego.InstanceBootOptions{}) } // Stop a host gracefully func (d *Driver) Stop() error { log.Debug("Stop...") - err := d.getClient().ShutdownInstance(context.TODO(), d.InstanceID) - return err + client, err := d.getClient() + if err != nil { + return err + } + return client.ShutdownInstance(context.TODO(), d.InstanceID) } // Remove a host func (d *Driver) Remove() error { - client := d.getClient() + client, err := d.getClient() + if err != nil { + return err + } log.Infof("Removing linode: %d", d.InstanceID) if err := client.DeleteInstance(context.TODO(), d.InstanceID); err != nil { if apiErr, ok := err.(*linodego.Error); ok && apiErr.Code == 404 { @@ -569,15 +596,21 @@ func (d *Driver) Remove() error { // have any special restart behaviour. func (d *Driver) Restart() error { log.Debug("Restarting...") - err := d.getClient().RebootInstance(context.TODO(), d.InstanceID, 0) - return err + client, err := d.getClient() + if err != nil { + return err + } + return client.RebootInstance(context.TODO(), d.InstanceID, linodego.InstanceRebootOptions{}) } // Kill stops a host forcefully func (d *Driver) Kill() error { log.Debug("Killing...") - err := d.getClient().ShutdownInstance(context.TODO(), d.InstanceID) - return err + client, err := d.getClient() + if err != nil { + return err + } + return client.ShutdownInstance(context.TODO(), d.InstanceID) } func (d *Driver) createSSHKey() (string, error) { From 6d36cbdc969beca6ce9b4c0cae00413fcf201af1 Mon Sep 17 00:00:00 2001 From: Zhiwei Liang Date: Tue, 21 Jul 2026 18:54:18 -0400 Subject: [PATCH 2/3] Handle wrapped not found errors --- pkg/drivers/linode/linode.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/drivers/linode/linode.go b/pkg/drivers/linode/linode.go index 0341d7f..8646b15 100644 --- a/pkg/drivers/linode/linode.go +++ b/pkg/drivers/linode/linode.go @@ -582,7 +582,7 @@ func (d *Driver) Remove() error { } log.Infof("Removing linode: %d", d.InstanceID) if err := client.DeleteInstance(context.TODO(), d.InstanceID); err != nil { - if apiErr, ok := err.(*linodego.Error); ok && apiErr.Code == 404 { + if linodego.IsNotFound(err) { log.Debug("Linode was already removed") return nil } From f0310e70c569e5f5e481613042fa9a7a6503677a Mon Sep 17 00:00:00 2001 From: Zhiwei Liang <121905282+zliang-akamai@users.noreply.github.com> Date: Tue, 21 Jul 2026 19:32:23 -0400 Subject: [PATCH 3/3] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- pkg/drivers/linode/linode.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/drivers/linode/linode.go b/pkg/drivers/linode/linode.go index 8646b15..4c06c77 100644 --- a/pkg/drivers/linode/linode.go +++ b/pkg/drivers/linode/linode.go @@ -500,7 +500,7 @@ func (d *Driver) Create() error { waitContext, cancel := context.WithTimeout(context.Background(), 180*time.Second) defer cancel() if _, err := client.WaitForInstanceStatus(waitContext, d.InstanceID, linodego.InstanceRunning); err != nil { - return fmt.Errorf("wait for machine running failed: %s", err) + return fmt.Errorf("wait for machine running failed: %w", err) } return nil