77 "github.com/docker/machine/libmachine/drivers"
88 "github.com/docker/machine/libmachine/engine"
99 "github.com/docker/machine/libmachine/log"
10+ "github.com/docker/machine/libmachine/mcndockerclient"
1011 "github.com/docker/machine/libmachine/mcnerror"
1112 "github.com/docker/machine/libmachine/mcnutils"
1213 "github.com/docker/machine/libmachine/provision"
@@ -15,6 +16,7 @@ import (
1516 "github.com/docker/machine/libmachine/ssh"
1617 "github.com/docker/machine/libmachine/state"
1718 "github.com/docker/machine/libmachine/swarm"
19+ "github.com/docker/machine/libmachine/versioncmp"
1820)
1921
2022var (
@@ -162,6 +164,24 @@ func (h *Host) Restart() error {
162164 return h .WaitForDocker ()
163165}
164166
167+ func (h * Host ) DockerVersion () (string , error ) {
168+ url , err := h .Driver .GetURL ()
169+ if err != nil {
170+ return "" , err
171+ }
172+
173+ dockerHost := & mcndockerclient.RemoteDocker {
174+ HostURL : url ,
175+ AuthOption : h .AuthOptions (),
176+ }
177+ dockerVersion , err := mcndockerclient .DockerVersion (dockerHost )
178+ if err != nil {
179+ return "" , err
180+ }
181+
182+ return dockerVersion , nil
183+ }
184+
165185func (h * Host ) Upgrade () error {
166186 machineState , err := h .Driver .GetState ()
167187 if err != nil {
@@ -180,6 +200,39 @@ func (h *Host) Upgrade() error {
180200 return err
181201 }
182202
203+ dockerVersion , err := h .DockerVersion ()
204+ if err != nil {
205+ return err
206+ }
207+
208+ // If we're upgrading from a pre-CE (e.g., 1.13.1) release to a CE
209+ // release (e.g., 17.03.0-ce), we should simply uninstall and
210+ // re-install from scratch, since the official package names will
211+ // change from 'docker-engine' to 'docker-ce'.
212+ if versioncmp .LessThanOrEqualTo (dockerVersion , provision .LastReleaseBeforeCEVersioning ) &&
213+ // RancherOS and boot2docker, being 'static ISO builds', have
214+ // an upgrade process which simply grabs the latest if it's
215+ // different, and so do not need to jump through this hoop to
216+ // upgrade safely.
217+ provisioner .String () != "rancheros" &&
218+ provisioner .String () != "boot2docker" {
219+
220+ // Name of pacakge 'docker-engine' will fall through in this
221+ // case, so that we execute, e.g.,
222+ //
223+ // 'sudo apt-get purge -y docker-engine'
224+ if err := provisioner .Package ("docker-engine" , pkgaction .Purge ); err != nil {
225+ return err
226+ }
227+
228+ // Then we kick off the normal provisioning process which will
229+ // go off and install Docker (get.docker.com script should work
230+ // fine to install Docker from scratch after removing the old
231+ // packages, and images/containers etc. should be preserved in
232+ // /var/lib/docker)
233+ return h .Provision ()
234+ }
235+
183236 log .Info ("Upgrading docker..." )
184237 if err := provisioner .Package ("docker" , pkgaction .Upgrade ); err != nil {
185238 return err
0 commit comments