diff --git a/agent/tools/tools_test.go b/agent/tools/tools_test.go index 2c469871706..1de702c355a 100644 --- a/agent/tools/tools_test.go +++ b/agent/tools/tools_test.go @@ -208,90 +208,53 @@ func (t *ToolsSuite) TestReadGUIArchiveSuccess(c *gc.C) { } func (t *ToolsSuite) TestChangeAgentTools(c *gc.C) { - tests := []struct { - version1 version.Binary - version2 version.Binary - dir1 string - dir2 string - }{ - { - version.MustParseBinary("1.2.3-quantal-amd64"), - version.MustParseBinary("1.2.4-quantal-amd64"), - "1.2.3-quantal-amd64", "1.2.4-quantal-amd64", - }, - { - version.MustParseBinary("1.2-beta1.3-quantal-amd64"), - version.MustParseBinary("1.2.4-quantal-amd64"), - "1.2-beta1-quantal-amd64", "1.2.4-quantal-amd64", - }, - { - version.MustParseBinary("1.2-beta1.3-quantal-amd64"), - version.MustParseBinary("1.2-beta2.4-quantal-amd64"), - "1.2-beta1-quantal-amd64", "1.2-beta2-quantal-amd64", - }, + files := []*testing.TarFile{ + testing.NewTarFile("jujuc", agenttools.DirPerm, "juju executable"), + testing.NewTarFile("jujud", agenttools.DirPerm, "jujuc executable"), } - for k, v := range tests { - if k != 0 { - t.dataDir = c.MkDir() - } - files := []*testing.TarFile{ - testing.NewTarFile("jujuc", agenttools.DirPerm, "juju executable"), - testing.NewTarFile("jujud", agenttools.DirPerm, "jujuc executable"), - } - data, checksum := testing.TarGz(files...) - testTools := &coretest.Tools{ - URL: "http://foo/bar1", - Version: v.version1, - Size: int64(len(data)), - SHA256: checksum, - } - err := agenttools.UnpackTools(t.dataDir, testTools, bytes.NewReader(data)) - c.Assert(err, jc.ErrorIsNil) + data, checksum := testing.TarGz(files...) + testTools := &coretest.Tools{ + URL: "http://foo/bar1", + Version: version.MustParseBinary("1.2.3-quantal-amd64"), + Size: int64(len(data)), + SHA256: checksum, + } + err := agenttools.UnpackTools(t.dataDir, testTools, bytes.NewReader(data)) + c.Assert(err, jc.ErrorIsNil) - gotTools, err := agenttools.ChangeAgentTools(t.dataDir, "testagent", testTools.Version) - c.Assert(err, jc.ErrorIsNil) - c.Assert(*gotTools, gc.Equals, *testTools) + gotTools, err := agenttools.ChangeAgentTools(t.dataDir, "testagent", testTools.Version) + c.Assert(err, jc.ErrorIsNil) + c.Assert(*gotTools, gc.Equals, *testTools) - assertDirNames(c, t.toolsDir(), []string{v.dir1, "testagent"}) - assertDirNames(c, agenttools.ToolsDir(t.dataDir, "testagent"), []string{"jujuc", "jujud", agenttools.ToolsFile}) + assertDirNames(c, t.toolsDir(), []string{"1.2.3-quantal-amd64", "testagent"}) + assertDirNames(c, agenttools.ToolsDir(t.dataDir, "testagent"), []string{"jujuc", "jujud", agenttools.ToolsFile}) - // Upgrade again to check that the link replacement logic works ok. - files2 := []*testing.TarFile{ - testing.NewTarFile("quantal", agenttools.DirPerm, "foo content"), - testing.NewTarFile("amd64", agenttools.DirPerm, "bar content"), - } - data2, checksum2 := testing.TarGz(files2...) - tools2 := &coretest.Tools{ - URL: "http://foo/bar2", - Version: v.version2, - Size: int64(len(data2)), - SHA256: checksum2, - } - err = agenttools.UnpackTools(t.dataDir, tools2, bytes.NewReader(data2)) - c.Assert(err, jc.ErrorIsNil) + // Upgrade again to check that the link replacement logic works ok. + files2 := []*testing.TarFile{ + testing.NewTarFile("quantal", agenttools.DirPerm, "foo content"), + testing.NewTarFile("amd64", agenttools.DirPerm, "bar content"), + } + data2, checksum2 := testing.TarGz(files2...) + tools2 := &coretest.Tools{ + URL: "http://foo/bar2", + Version: version.MustParseBinary("1.2.4-quantal-amd64"), + Size: int64(len(data2)), + SHA256: checksum2, + } + err = agenttools.UnpackTools(t.dataDir, tools2, bytes.NewReader(data2)) + c.Assert(err, jc.ErrorIsNil) - gotTools, err = agenttools.ChangeAgentTools(t.dataDir, "testagent", tools2.Version) - c.Assert(err, jc.ErrorIsNil) - c.Assert(*gotTools, gc.Equals, *tools2) + gotTools, err = agenttools.ChangeAgentTools(t.dataDir, "testagent", tools2.Version) + c.Assert(err, jc.ErrorIsNil) + c.Assert(*gotTools, gc.Equals, *tools2) - assertDirNames(c, t.toolsDir(), []string{v.dir1, v.dir2, "testagent"}) - assertDirNames(c, agenttools.ToolsDir(t.dataDir, "testagent"), []string{"quantal", "amd64", agenttools.ToolsFile}) - } + assertDirNames(c, t.toolsDir(), []string{"1.2.3-quantal-amd64", "1.2.4-quantal-amd64", "testagent"}) + assertDirNames(c, agenttools.ToolsDir(t.dataDir, "testagent"), []string{"quantal", "amd64", agenttools.ToolsFile}) } func (t *ToolsSuite) TestSharedToolsDir(c *gc.C) { - tests := []struct { - dataDir string - version version.Binary - out string - }{ - {"/var/lib/juju", version.MustParseBinary("1.2.3-precise-amd64"), "/var/lib/juju/tools/1.2.3-precise-amd64"}, - {"/var/lib/juju", version.MustParseBinary("1.2-beta1.3-precise-amd64"), "/var/lib/juju/tools/1.2-beta1-precise-amd64"}, - } - for _, v := range tests { - dir := agenttools.SharedToolsDir(v.dataDir, v.version) - c.Assert(dir, gc.Equals, v.out) - } + dir := agenttools.SharedToolsDir("/var/lib/juju", version.MustParseBinary("1.2.3-precise-amd64")) + c.Assert(dir, gc.Equals, "/var/lib/juju/tools/1.2.3-precise-amd64") } func (t *ToolsSuite) TestSharedGUIDir(c *gc.C) { diff --git a/agent/tools/toolsdir.go b/agent/tools/toolsdir.go index 6b09f337115..7b4507e8da6 100644 --- a/agent/tools/toolsdir.go +++ b/agent/tools/toolsdir.go @@ -33,7 +33,6 @@ const ( // store binaries for the given version of the juju tools // within the dataDir directory. func SharedToolsDir(dataDir string, vers version.Binary) string { - vers.Number = vers.Number.ToPatch() return path.Join(dataDir, "tools", vers.String()) } diff --git a/apiserver/facades/controller/caasoperatorprovisioner/provisioner.go b/apiserver/facades/controller/caasoperatorprovisioner/provisioner.go index b5a26152525..15f37544f75 100644 --- a/apiserver/facades/controller/caasoperatorprovisioner/provisioner.go +++ b/apiserver/facades/controller/caasoperatorprovisioner/provisioner.go @@ -23,6 +23,7 @@ import ( "github.com/juju/juju/state/watcher" "github.com/juju/juju/storage" "github.com/juju/juju/storage/poolmanager" + "github.com/juju/juju/version" ) type API struct { @@ -113,7 +114,7 @@ func (a *API) OperatorProvisioningInfo() (params.OperatorProvisioningInfo, error ) } - imagePath := podcfg.GetJujuOCIImagePath(cfg, vers) + imagePath := podcfg.GetJujuOCIImagePath(cfg, vers.ToPatch(), version.OfficialBuild) storageClassName, _ := modelConfig.AllAttrs()[provider.OperatorStorageKey].(string) if storageClassName == "" { return params.OperatorProvisioningInfo{}, errors.New("no operator storage class defined") diff --git a/apiserver/facades/controller/caasoperatorprovisioner/provisioner_test.go b/apiserver/facades/controller/caasoperatorprovisioner/provisioner_test.go index a89bc7a1e50..d61fda8b282 100644 --- a/apiserver/facades/controller/caasoperatorprovisioner/provisioner_test.go +++ b/apiserver/facades/controller/caasoperatorprovisioner/provisioner_test.go @@ -24,6 +24,7 @@ import ( "github.com/juju/juju/core/life" "github.com/juju/juju/state" coretesting "github.com/juju/juju/testing" + jujuversion "github.com/juju/juju/version" ) var _ = gc.Suite(&CAASProvisionerSuite{}) @@ -44,6 +45,7 @@ func (s *CAASProvisionerSuite) SetUpTest(c *gc.C) { s.resources = common.NewResources() s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() }) + s.PatchValue(&jujuversion.OfficialBuild, 666) s.authorizer = &apiservertesting.FakeAuthorizer{ Tag: names.NewMachineTag("0"), @@ -131,7 +133,7 @@ func (s *CAASProvisionerSuite) TestOperatorProvisioningInfoDefault(c *gc.C) { result, err := s.api.OperatorProvisioningInfo() c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, params.OperatorProvisioningInfo{ - ImagePath: "jujusolutions/jujud-operator:2.6-beta3", + ImagePath: "jujusolutions/jujud-operator:2.6-beta3.666", Version: version.MustParse("2.6-beta3"), APIAddresses: []string{"10.0.0.1:1"}, Tags: map[string]string{ @@ -157,7 +159,7 @@ func (s *CAASProvisionerSuite) TestOperatorProvisioningInfo(c *gc.C) { result, err := s.api.OperatorProvisioningInfo() c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, params.OperatorProvisioningInfo{ - ImagePath: s.st.operatorRepo + "/jujud-operator:" + "2.6-beta3", + ImagePath: s.st.operatorRepo + "/jujud-operator:" + "2.6-beta3.666", Version: version.MustParse("2.6-beta3"), APIAddresses: []string{"10.0.0.1:1"}, Tags: map[string]string{ @@ -184,7 +186,7 @@ func (s *CAASProvisionerSuite) TestOperatorProvisioningInfoNoStoragePool(c *gc.C result, err := s.api.OperatorProvisioningInfo() c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, params.OperatorProvisioningInfo{ - ImagePath: s.st.operatorRepo + "/jujud-operator:" + "2.6-beta3", + ImagePath: s.st.operatorRepo + "/jujud-operator:" + "2.6-beta3.666", Version: version.MustParse("2.6-beta3"), APIAddresses: []string{"10.0.0.1:1"}, Tags: map[string]string{ diff --git a/apiserver/facades/controller/caasunitprovisioner/provisioner.go b/apiserver/facades/controller/caasunitprovisioner/provisioner.go index b20fc3263e2..ed5f6f2141a 100644 --- a/apiserver/facades/controller/caasunitprovisioner/provisioner.go +++ b/apiserver/facades/controller/caasunitprovisioner/provisioner.go @@ -31,6 +31,7 @@ import ( "github.com/juju/juju/state/watcher" "github.com/juju/juju/storage" "github.com/juju/juju/storage/poolmanager" + "github.com/juju/juju/version" ) var logger = loggo.GetLogger("juju.apiserver.controller.caasunitprovisioner") @@ -276,7 +277,7 @@ func (f *Facade) provisioningInfo(model Model, tagString string) (*params.Kubern fmt.Sprintf("agent version is missing in model config %q", modelConfig.Name()), ) } - operatorImagePath := podcfg.GetJujuOCIImagePath(controllerCfg, vers) + operatorImagePath := podcfg.GetJujuOCIImagePath(controllerCfg, vers.ToPatch(), version.OfficialBuild) filesystemParams, err := f.applicationFilesystemParams(app, controllerCfg, modelConfig) if err != nil { diff --git a/apiserver/facades/controller/caasunitprovisioner/provisioner_test.go b/apiserver/facades/controller/caasunitprovisioner/provisioner_test.go index 01287cddefb..c56ab7d9197 100644 --- a/apiserver/facades/controller/caasunitprovisioner/provisioner_test.go +++ b/apiserver/facades/controller/caasunitprovisioner/provisioner_test.go @@ -90,6 +90,7 @@ func (s *CAASProvisionerSuite) SetUpTest(c *gc.C) { Controller: true, } s.clock = testclock.NewClock(time.Now()) + s.PatchValue(&jujuversion.OfficialBuild, 666) facade, err := caasunitprovisioner.NewFacade( s.resources, s.authorizer, s.st, s.storage, s.devices, s.storagePoolManager, s.registry, s.clock) @@ -201,7 +202,7 @@ func (s *CAASProvisionerSuite) TestProvisioningInfo(c *gc.C) { DeploymentType: "stateful", ServiceType: "loadbalancer", }, - OperatorImagePath: fmt.Sprintf("jujusolutions/jujud-operator:%s", jujuversion.Current.String()), + OperatorImagePath: fmt.Sprintf("jujusolutions/jujud-operator:%s", jujuversion.Current.String()+".666"), Devices: []params.KubernetesDeviceParams{ { Type: "nvidia.com/gpu", diff --git a/caas/kubernetes/provider/bootstrap_test.go b/caas/kubernetes/provider/bootstrap_test.go index 28e6d0f2760..456e5630664 100644 --- a/caas/kubernetes/provider/bootstrap_test.go +++ b/caas/kubernetes/provider/bootstrap_test.go @@ -65,6 +65,7 @@ func (s *bootstrapSuite) SetUpTest(c *gc.C) { c.Assert(err, jc.ErrorIsNil) pcfg.JujuVersion = jujuversion.Current + pcfg.OfficialBuild = 666 pcfg.APIInfo = &api.Info{ Password: "password", CACert: testing.CACert, @@ -559,7 +560,7 @@ func (s *bootstrapSuite) TestBootstrap(c *gc.C) { { Name: "api-server", ImagePullPolicy: core.PullIfNotPresent, - Image: "jujusolutions/jujud-operator:" + jujuversion.Current.String(), + Image: "jujusolutions/jujud-operator:" + jujuversion.Current.String() + ".666", Command: []string{ "/bin/sh", }, diff --git a/cloudconfig/podcfg/image.go b/cloudconfig/podcfg/image.go index b81b995d7f4..b579c3b0bd1 100644 --- a/cloudconfig/podcfg/image.go +++ b/cloudconfig/podcfg/image.go @@ -20,7 +20,7 @@ const ( // GetControllerImagePath returns oci image path of jujud for a controller. func (cfg *ControllerPodConfig) GetControllerImagePath() string { - return GetJujuOCIImagePath(cfg.Controller.Config, cfg.JujuVersion) + return GetJujuOCIImagePath(cfg.Controller.Config, cfg.JujuVersion, cfg.OfficialBuild) } // GetJujuDbOCIImagePath returns the juju-db oci image path. @@ -39,8 +39,9 @@ func IsJujuOCIImage(imagePath string) bool { } // GetJujuOCIImagePath returns the jujud oci image path. -func GetJujuOCIImagePath(controllerCfg controller.Config, ver version.Number) string { +func GetJujuOCIImagePath(controllerCfg controller.Config, ver version.Number, build int) string { // First check the deprecated "caas-operator-image-path" config. + ver.Build = build imagePath := RebuildOldOperatorImagePath( controllerCfg.CAASOperatorImagePath(), ver, ) diff --git a/cloudconfig/podcfg/image_test.go b/cloudconfig/podcfg/image_test.go index 3b40ccd518b..70fe89fcba2 100644 --- a/cloudconfig/podcfg/image_test.go +++ b/cloudconfig/podcfg/image_test.go @@ -24,10 +24,10 @@ func (*imageSuite) TestGetJujuOCIImagePath(c *gc.C) { cfg[controller.CAASImageRepo] = "testing-repo" ver := version.MustParse("2.6-beta3") - path := podcfg.GetJujuOCIImagePath(cfg, ver) - c.Assert(path, jc.DeepEquals, "testing-repo/jujud-operator:2.6-beta3") + path := podcfg.GetJujuOCIImagePath(cfg, ver, 666) + c.Assert(path, jc.DeepEquals, "testing-repo/jujud-operator:2.6-beta3.666") cfg[controller.CAASOperatorImagePath] = "testing-old-repo/jujud-old-operator:1.6" - path = podcfg.GetJujuOCIImagePath(cfg, ver) + path = podcfg.GetJujuOCIImagePath(cfg, ver, 0) c.Assert(path, jc.DeepEquals, "testing-old-repo/jujud-old-operator:2.6-beta3") } diff --git a/cloudconfig/podcfg/podcfg.go b/cloudconfig/podcfg/podcfg.go index d8c314fdb22..b9a2bde8e09 100644 --- a/cloudconfig/podcfg/podcfg.go +++ b/cloudconfig/podcfg/podcfg.go @@ -60,6 +60,9 @@ type ControllerPodConfig struct { // JujuVersion is the juju version. JujuVersion version.Number + // OfficialBuild is the build number to use when pulling the juju oci image. + OfficialBuild int + // DataDir holds the directory that juju state will be put in the new // instance. DataDir string diff --git a/cloudconfig/podcfg/podcfg_test.go b/cloudconfig/podcfg/podcfg_test.go index e937dcadaa1..876145fd6a9 100644 --- a/cloudconfig/podcfg/podcfg_test.go +++ b/cloudconfig/podcfg/podcfg_test.go @@ -65,7 +65,8 @@ func (*podcfgSuite) TestOperatorImagesDefaultRepo(c *gc.C) { ) c.Assert(err, jc.ErrorIsNil) podConfig.JujuVersion = version.MustParse("6.6.6") - c.Assert(podConfig.GetControllerImagePath(), gc.Equals, "jujusolutions/jujud-operator:6.6.6") + podConfig.OfficialBuild = 666 + c.Assert(podConfig.GetControllerImagePath(), gc.Equals, "jujusolutions/jujud-operator:6.6.6.666") c.Assert(podConfig.GetJujuDbOCIImagePath(), gc.Equals, "jujusolutions/juju-db:4.0") } @@ -80,7 +81,8 @@ func (*podcfgSuite) TestOperatorImagesCustomRepo(c *gc.C) { ) c.Assert(err, jc.ErrorIsNil) podConfig.JujuVersion = version.MustParse("6.6.6") - c.Assert(podConfig.GetControllerImagePath(), gc.Equals, "path/to/my/repo/jujud-operator:6.6.6") + podConfig.OfficialBuild = 666 + c.Assert(podConfig.GetControllerImagePath(), gc.Equals, "path/to/my/repo/jujud-operator:6.6.6.666") c.Assert(podConfig.GetJujuDbOCIImagePath(), gc.Equals, "path/to/my/repo/juju-db:4.0") } diff --git a/cloudconfig/userdatacfg.go b/cloudconfig/userdatacfg.go index 53480505cfa..45ed7b4c9bc 100644 --- a/cloudconfig/userdatacfg.go +++ b/cloudconfig/userdatacfg.go @@ -189,13 +189,11 @@ func (c *baseConfigure) toolsSymlinkCommand(toolsDir string) string { c.icfg.AgentVersion(), ) default: - ver := c.icfg.AgentVersion() - ver.Number = ver.ToPatch() // TODO(dfc) ln -nfs, so it doesn't fail if for some reason that // the target already exists. return fmt.Sprintf( "ln -s %v %s", - ver.String(), + c.icfg.AgentVersion(), shquote(toolsDir), ) } diff --git a/cloudconfig/userdatacfg_test.go b/cloudconfig/userdatacfg_test.go index dda70e419ca..edbe0dddb18 100644 --- a/cloudconfig/userdatacfg_test.go +++ b/cloudconfig/userdatacfg_test.go @@ -392,7 +392,7 @@ mkdir -p /var/lib/juju/locks \(id ubuntu &> /dev/null\) && chown ubuntu:ubuntu /var/lib/juju/locks mkdir -p /var/log/juju chown syslog:adm /var/log/juju -bin='/var/lib/juju/tools/1\.2\.3-precise-amd64' +bin='/var/lib/juju/tools/1\.2\.3\.123-precise-amd64' mkdir -p \$bin echo 'Fetching Juju agent version.* curl .* '.*' --retry 10 -o \$bin/tools\.tar\.gz 'http://foo\.com/tools/released/juju1\.2\.3\.123-precise-amd64\.tgz' @@ -406,10 +406,10 @@ chmod 0600 '/var/lib/juju/agents/machine-0/agent\.conf' install -D -m 600 /dev/null '/var/lib/juju/bootstrap-params' printf '%s\\n' '.*' > '/var/lib/juju/bootstrap-params' echo 'Installing Juju machine agent'.* -/var/lib/juju/tools/1\.2\.3-precise-amd64/jujud bootstrap-state --timeout 10m0s --data-dir '/var/lib/juju' --debug '/var/lib/juju/bootstrap-params' +/var/lib/juju/tools/1\.2\.3\.123-precise-amd64/jujud bootstrap-state --timeout 10m0s --data-dir '/var/lib/juju' --debug '/var/lib/juju/bootstrap-params' install -D -m 755 /dev/null '/sbin/remove-juju-services' printf '%s\\n' '.*' > '/sbin/remove-juju-services' -ln -s 1\.2\.3-precise-amd64 '/var/lib/juju/tools/machine-0' +ln -s 1\.2\.3\.123-precise-amd64 '/var/lib/juju/tools/machine-0' echo 'Starting Juju machine agent \(service jujud-machine-0\)'.* cat > /etc/init/jujud-machine-0\.conf << 'EOF'\\ndescription "juju agent for machine-0"\\nauthor "Juju Team "\\nstart on runlevel \[2345\]\\nstop on runlevel \[!2345\]\\nrespawn\\nnormal exit 0\\n\\nlimit .*\\n\\nscript\\n\\n\\n # Ensure log files are properly protected\\n touch /var/log/juju/machine-0\.log\\n chown syslog:adm /var/log/juju/machine-0\.log\\n chmod 0640 /var/log/juju/machine-0\.log\\n\\n exec '/var/lib/juju/tools/machine-0/jujud' machine --data-dir '/var/lib/juju' --machine-id 0 --debug >> /var/log/juju/machine-0\.log 2>&1\\nend script\\nEOF\\n start jujud-machine-0 diff --git a/cmd/juju/commands/upgradecontroller.go b/cmd/juju/commands/upgradecontroller.go index bbf586f5ca1..c29d6bc5869 100644 --- a/cmd/juju/commands/upgradecontroller.go +++ b/cmd/juju/commands/upgradecontroller.go @@ -241,7 +241,7 @@ func initCAASVersions( filterVersion.Major-- } logger.Debugf("searching for agent images with major: %d", filterVersion.Major) - imagePath := podcfg.GetJujuOCIImagePath(controllerCfg, version.Zero) + imagePath := podcfg.GetJujuOCIImagePath(controllerCfg, version.Zero, 0) availableTags, err := docker.ListOperatorImages(imagePath) if err != nil { return nil, err diff --git a/cmd/supercommand.go b/cmd/supercommand.go index 8cac237b545..e1543cc47ef 100644 --- a/cmd/supercommand.go +++ b/cmd/supercommand.go @@ -42,8 +42,8 @@ type versionDetail struct { GitTreeState string `json:"git-tree-state,omitempty" yaml:"git-tree-state,omitempty"` // Compiler reported by runtime.Compiler Compiler string `json:"compiler" yaml:"compiler"` - // Build is a monotonic integer set by Jenkins. - Build int `json:"build,omitempty" yaml:"build,omitempty"` + // OfficialBuild is a monotonic integer set by Jenkins. + OfficialBuild int `json:"official-build,omitempty" yaml:"official-build,omitempty"` } // NewSuperCommand is like cmd.NewSuperCommand but @@ -62,11 +62,11 @@ func NewSuperCommand(p cmd.SuperCommandParams) *cmd.SuperCommand { Series: series.MustHostSeries(), } detail := versionDetail{ - Version: current.String(), - GitCommit: jujuversion.GitCommit, - GitTreeState: jujuversion.GitTreeState, - Compiler: jujuversion.Compiler, - Build: jujuversion.Build, + Version: current.String(), + GitCommit: jujuversion.GitCommit, + GitTreeState: jujuversion.GitTreeState, + Compiler: jujuversion.Compiler, + OfficialBuild: jujuversion.OfficialBuild, } // p.Version should be a version.Binary, but juju/cmd does not @@ -80,7 +80,7 @@ func NewSuperCommand(p cmd.SuperCommandParams) *cmd.SuperCommand { } func runNotifier(name string) { - logger.Infof("running %s [%s %s %s %s]", name, jujuversion.Current, jujuversion.GitCommit, runtime.Compiler, runtime.Version()) + logger.Infof("running %s [%s %d %s %s %s]", name, jujuversion.Current, jujuversion.OfficialBuild, jujuversion.GitCommit, runtime.Compiler, runtime.Version()) logger.Debugf(" args: %#v", os.Args) } diff --git a/environs/bootstrap/bootstrap.go b/environs/bootstrap/bootstrap.go index cbac8eee1a4..a94384f0b44 100644 --- a/environs/bootstrap/bootstrap.go +++ b/environs/bootstrap/bootstrap.go @@ -277,6 +277,7 @@ func bootstrapCAAS( return errors.Trace(err) } podConfig.JujuVersion = jujuVersion + podConfig.OfficialBuild = jujuversion.OfficialBuild if err := finalizePodBootstrapConfig(podConfig, args, environ.Config()); err != nil { return errors.Annotate(err, "finalizing bootstrap instance config") } diff --git a/environs/bootstrap/tools.go b/environs/bootstrap/tools.go index ee50c687cb7..f65d5760142 100644 --- a/environs/bootstrap/tools.go +++ b/environs/bootstrap/tools.go @@ -66,16 +66,9 @@ func findPackagedTools( // one is configured in the environment. if vers == nil { if agentVersion, ok := env.Config().AgentVersion(); ok { - configVersion := agentVersion.ToPatch() - vers = &configVersion + vers = &agentVersion } - } else { - // We don't care about the build version here when looking for packaged - // tools. - buildLessVersion := vers.ToPatch() - vers = &buildLessVersion } - logger.Infof("looking for bootstrap agent binaries: version=%v", vers) toolsList, findToolsErr := findBootstrapTools(env, vers, arch, series) logger.Infof("found %d packaged agent binaries", len(toolsList)) diff --git a/environs/bootstrap/tools_test.go b/environs/bootstrap/tools_test.go index fab3df1aed2..36b0112001f 100644 --- a/environs/bootstrap/tools_test.go +++ b/environs/bootstrap/tools_test.go @@ -96,8 +96,8 @@ func (s *toolsSuite) TestFindBootstrapTools(c *gc.C) { return nil, nil }) - vers := version.MustParse("1.2.1.4") - devVers := version.MustParse("1.2-beta1.4") + vers := version.MustParse("1.2.1") + devVers := version.MustParse("1.2-beta1") arm64 := "arm64" type test struct { @@ -150,12 +150,10 @@ func (s *toolsSuite) TestFindBootstrapTools(c *gc.C) { if test.streams != nil { extra["agent-stream"] = test.streams[0] } - env := newEnviron("foo", useDefaultKeys, extra) bootstrap.FindBootstrapTools(env, test.version, test.arch, test.series) c.Assert(called, gc.Equals, i+1) c.Assert(filter, gc.Equals, test.filter) - if test.streams != nil { c.Check(findStreams, gc.DeepEquals, test.streams) } else { @@ -196,19 +194,14 @@ func (s *toolsSuite) TestFindAvailableToolsSpecificVersion(c *gc.C) { } currentVersion.Major = 2 currentVersion.Minor = 3 - s.PatchValue(&jujuversion.Current, currentVersion.Number) - var findToolsCalled int s.PatchValue(bootstrap.FindTools, func(_ environs.BootstrapEnviron, major, minor int, streams []string, f tools.Filter) (tools.List, error) { c.Assert(f.Number.Major, gc.Equals, 10) c.Assert(f.Number.Minor, gc.Equals, 11) c.Assert(f.Number.Patch, gc.Equals, 12) - c.Assert(f.Number.Build, gc.Equals, 0) c.Assert(streams, gc.DeepEquals, []string{"released"}) - findToolsCalled++ - return []*tools.Tools{ { Version: currentVersion, @@ -217,10 +210,7 @@ func (s *toolsSuite) TestFindAvailableToolsSpecificVersion(c *gc.C) { }, nil }) env := newEnviron("foo", useDefaultKeys, nil) - - toolsVersion := version.MustParse("10.11.12.20") - c.Assert(toolsVersion.Build, gc.Equals, 20) - + toolsVersion := version.MustParse("10.11.12") result, err := bootstrap.FindPackagedTools(env, &toolsVersion, nil, nil) c.Assert(err, jc.ErrorIsNil) c.Assert(findToolsCalled, gc.Equals, 1) diff --git a/version/version.go b/version/version.go index 96072b52302..b12107a5d2d 100644 --- a/version/version.go +++ b/version/version.go @@ -37,14 +37,13 @@ var switchOverVersion = semversion.MustParse("1.19.9") // build is injected by Jenkins, it must be an integer or empty. var build string -// Build is a monotonic number injected by Jenkins. It is added to the Current version only when -// the version is a development build (see IsDev(1)) -var Build = mustParseBuildInt(build) +// OfficialBuild is a monotonic number injected by Jenkins. +var OfficialBuild = mustParseBuildInt(build) // Current gives the current version of the system. If the file // "FORCE-VERSION" is present in the same directory as the running // binary, it will override this. -var Current = mustParseVersion(version, build) +var Current = semversion.MustParse(version) // Compiler is the go compiler used to build the binary. var Compiler = runtime.Compiler @@ -85,14 +84,6 @@ func IsDev(v semversion.Number) bool { return v.Tag != "" || v.Build > 0 } -func mustParseVersion(versionStr string, buildInt string) semversion.Number { - ver := semversion.MustParse(versionStr) - if IsDev(ver) { - ver.Build = mustParseBuildInt(buildInt) - } - return ver -} - func mustParseBuildInt(buildInt string) int { if buildInt == "" { return 0 diff --git a/worker/upgrader/upgrader.go b/worker/upgrader/upgrader.go index 1aabdbfe488..54c33461322 100644 --- a/worker/upgrader/upgrader.go +++ b/worker/upgrader/upgrader.go @@ -193,12 +193,21 @@ func (u *Upgrader) loop() error { } logger.Infof("desired agent binary version: %v", wantVersion) - if wantVersion == jujuversion.Current { + // If we have a desired version of Juju without the build number, ie it is + // not a user compiled version, reset the build number of the current version + // to remove the Jenkins build number. We don't care about the Jenkins build + // number when doing an upgrade check. + haveVersion := jujuversion.Current + if wantVersion.Build == 0 { + haveVersion.Build = 0 + } + + if wantVersion == haveVersion { u.config.InitialUpgradeCheckComplete.Unlock() continue } else if !AllowedTargetVersion( u.config.OrigAgentVersion, - jujuversion.Current, + haveVersion, !u.config.UpgradeStepsWaiter.IsUnlocked(), wantVersion, ) { @@ -208,16 +217,16 @@ func (u *Upgrader) loop() error { // downgrade when its associate machine agent has not // finished upgrading. logger.Infof("desired agent binary version: %s is older than current %s, refusing to downgrade", - wantVersion, jujuversion.Current) + wantVersion, haveVersion) u.config.InitialUpgradeCheckComplete.Unlock() continue } - logger.Infof("upgrade requested from %v to %v", jujuversion.Current, wantVersion) + logger.Infof("upgrade requested from %v to %v", haveVersion, wantVersion) // Check if tools have already been downloaded. wantVersionBinary := toBinaryVersion(wantVersion) if u.toolsAlreadyDownloaded(wantVersionBinary) { - return u.newUpgradeReadyError(wantVersionBinary) + return u.newUpgradeReadyError(haveVersion, wantVersionBinary) } // Check if tools are available for download. @@ -240,7 +249,7 @@ func (u *Upgrader) loop() error { } err = u.ensureTools(wantTools) if err == nil { - return u.newUpgradeReadyError(wantTools.Version) + return u.newUpgradeReadyError(haveVersion, wantTools.Version) } logger.Errorf("failed to fetch agent binaries from %q: %v", wantTools.URL, err) } @@ -262,9 +271,9 @@ func (u *Upgrader) toolsAlreadyDownloaded(wantVersion version.Binary) bool { return err == nil } -func (u *Upgrader) newUpgradeReadyError(newVersion version.Binary) *UpgradeReadyError { +func (u *Upgrader) newUpgradeReadyError(haveVersion version.Number, newVersion version.Binary) *UpgradeReadyError { return &UpgradeReadyError{ - OldTools: toBinaryVersion(jujuversion.Current), + OldTools: toBinaryVersion(haveVersion), NewTools: newVersion, AgentName: u.tag.String(), DataDir: u.dataDir, diff --git a/worker/upgrader/upgrader_test.go b/worker/upgrader/upgrader_test.go index 75ab0f7050d..651f9f6a02f 100644 --- a/worker/upgrader/upgrader_test.go +++ b/worker/upgrader/upgrader_test.go @@ -75,7 +75,9 @@ func (s *UpgraderSuite) SetUpTest(c *gc.C) { func (s *UpgraderSuite) patchVersion(v version.Binary) { s.PatchValue(&arch.HostArch, func() string { return v.Arch }) s.PatchValue(&series.MustHostSeries, func() string { return v.Series }) - s.PatchValue(&jujuversion.Current, v.Number) + vers := v.Number + vers.Build = 666 + s.PatchValue(&jujuversion.Current, vers) } type mockConfig struct { @@ -131,6 +133,7 @@ func (s *UpgraderSuite) TestUpgraderSetsTools(c *gc.C) { s.machine.Refresh() gotTools, err := s.machine.AgentTools() c.Assert(err, jc.ErrorIsNil) + agentTools.Version.Build = 666 envtesting.CheckTools(c, gotTools, agentTools) } @@ -152,6 +155,7 @@ func (s *UpgraderSuite) TestUpgraderSetVersion(c *gc.C) { s.machine.Refresh() gotTools, err := s.machine.AgentTools() c.Assert(err, jc.ErrorIsNil) + vers.Build = 666 c.Assert(gotTools, gc.DeepEquals, &coretools.Tools{Version: vers}) }