diff --git a/.github/workflows/microk8s-tests.yml b/.github/workflows/microk8s-tests.yml index c5bb43aa56bd..73ef55300cc4 100644 --- a/.github/workflows/microk8s-tests.yml +++ b/.github/workflows/microk8s-tests.yml @@ -130,7 +130,7 @@ jobs: if: ${{ failure() }} - name: Upload debug log - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v2 + uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v2 with: name: juju-debug-actions path: juju-debug.log @@ -158,7 +158,7 @@ jobs: if: ${{ failure() }} - name: Upload inspect tarball - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v2 + uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v2 with: name: inspection-report-actions path: ./inspection-report-${{ strategy.job-index }}.tar.gz @@ -174,7 +174,7 @@ jobs: if: ${{ failure() }} - name: Upload kubectl describe - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v2 + uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v2 with: name: kubectl-describe-actions path: describe/*.describe @@ -192,7 +192,7 @@ jobs: if: ${{ failure() }} - name: Upload kubeflow pod logs - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v2 + uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v2 with: name: kubectl-stdout-actions path: stdout/*.log diff --git a/agent/agentbootstrap/bootstrap.go b/agent/agentbootstrap/bootstrap.go index c1abd0791187..910e4407c8af 100644 --- a/agent/agentbootstrap/bootstrap.go +++ b/agent/agentbootstrap/bootstrap.go @@ -12,7 +12,6 @@ import ( "github.com/juju/loggo/v2" "github.com/juju/mgo/v3" "github.com/juju/names/v5" - utilseries "github.com/juju/os/v2/series" "github.com/juju/juju/agent" "github.com/juju/juju/caas" @@ -20,12 +19,12 @@ import ( "github.com/juju/juju/cloud" "github.com/juju/juju/controller/modelmanager" coreagent "github.com/juju/juju/core/agent" - corebase "github.com/juju/juju/core/base" "github.com/juju/juju/core/credential" coredatabase "github.com/juju/juju/core/database" "github.com/juju/juju/core/instance" "github.com/juju/juju/core/model" corenetwork "github.com/juju/juju/core/network" + coreos "github.com/juju/juju/core/os" "github.com/juju/juju/core/permission" userbootstrap "github.com/juju/juju/domain/access/bootstrap" cloudbootstrap "github.com/juju/juju/domain/cloud/bootstrap" @@ -611,12 +610,7 @@ func (b *AgentBootstrap) initBootstrapMachine( hardware = *stateParams.BootstrapMachineHardwareCharacteristics } - hostSeries, err := utilseries.HostSeries() - if err != nil { - return nil, errors.Trace(err) - } - - base, err := corebase.GetBaseFromSeries(hostSeries) + base, err := coreos.HostBase() if err != nil { return nil, errors.Trace(err) } diff --git a/api/agent/upgradeseries/upgradeseries.go b/api/agent/upgradeseries/upgradeseries.go index 02e03c75f3d2..d03e7176d55d 100644 --- a/api/agent/upgradeseries/upgradeseries.go +++ b/api/agent/upgradeseries/upgradeseries.go @@ -78,47 +78,6 @@ func (s *Client) MachineStatus() (model.UpgradeSeriesStatus, error) { return "", errors.Trace(r.Error) } -// CurrentSeries returns what Juju thinks the current series of the machine is. -// Note that a machine could have been upgraded out-of-band by running -// do-release-upgrade outside of the upgrade-machine workflow, -// making this value incorrect. -func (s *Client) CurrentSeries() (string, error) { - series, err := s.series("CurrentSeries") - return series, errors.Trace(err) -} - -// TargetSeries returns the series that a machine has been locked -// for upgrading to. -func (s *Client) TargetSeries() (string, error) { - series, err := s.series("TargetSeries") - return series, errors.Trace(err) -} - -func (s *Client) series(methodName string) (string, error) { - var results params.StringResults - args := params.Entities{ - Entities: []params.Entity{{Tag: s.authTag.String()}}, - } - - err := s.facade.FacadeCall(context.TODO(), methodName, args, &results) - if err != nil { - return "", errors.Trace(err) - } - if len(results.Results) != 1 { - return "", errors.Errorf("expected 1 result, got %d", len(results.Results)) - } - - r := results.Results[0] - if r.Error == nil { - return r.Result, nil - } - - if params.IsCodeNotFound(r.Error) { - return "", errors.NewNotFound(r.Error, "") - } - return "", errors.Trace(r.Error) -} - // UnitsPrepared returns the units running on this machine that have // completed their upgrade-machine preparation, and are ready to be stopped and // have their unit agent services converted for the target series. @@ -220,18 +179,14 @@ func (s *Client) StartUnitCompletion(reason string) error { // completely finished, passing the current host OS series. // We use the name "Finish" to distinguish this method from the various // "Complete" phases. -func (s *Client) FinishUpgradeSeries(hostSeries string) error { +func (s *Client) FinishUpgradeSeries(hostBase corebase.Base) error { var results params.ErrorResults - base, err := corebase.GetBaseFromSeries(hostSeries) - if err != nil { - return errors.Trace(err) - } args := params.UpdateChannelArgs{Args: []params.UpdateChannelArg{{ Entity: params.Entity{Tag: s.authTag.String()}, - Channel: base.Channel.Track, + Channel: hostBase.Channel.Track, }}} - err = s.facade.FacadeCall(context.TODO(), "FinishUpgradeSeries", args, &results) + err := s.facade.FacadeCall(context.TODO(), "FinishUpgradeSeries", args, &results) if err != nil { return err } diff --git a/api/agent/upgradeseries/upgradeseries_test.go b/api/agent/upgradeseries/upgradeseries_test.go index e71663d70469..9c5fb8ab9861 100644 --- a/api/agent/upgradeseries/upgradeseries_test.go +++ b/api/agent/upgradeseries/upgradeseries_test.go @@ -13,6 +13,7 @@ import ( "github.com/juju/juju/api/agent/upgradeseries" "github.com/juju/juju/api/base/mocks" + corebase "github.com/juju/juju/core/base" "github.com/juju/juju/core/model" "github.com/juju/juju/core/status" "github.com/juju/juju/rpc/params" @@ -98,44 +99,6 @@ func (s *upgradeSeriesSuite) TestSetMachineStatus(c *gc.C) { c.Assert(err, gc.IsNil) } -func (s *upgradeSeriesSuite) TestCurrentSeries(c *gc.C) { - ctrl := gomock.NewController(c) - defer ctrl.Finish() - - fCaller := mocks.NewMockFacadeCaller(ctrl) - - resultSource := params.StringResults{ - Results: []params.StringResult{{ - Result: "xenial", - }}, - } - fCaller.EXPECT().FacadeCall(gomock.Any(), "CurrentSeries", s.args, gomock.Any()).SetArg(3, resultSource) - - api := upgradeseries.NewStateFromCaller(fCaller, s.tag) - target, err := api.CurrentSeries() - c.Assert(err, gc.IsNil) - c.Check(target, gc.Equals, "xenial") -} - -func (s *upgradeSeriesSuite) TestTargetSeries(c *gc.C) { - ctrl := gomock.NewController(c) - defer ctrl.Finish() - - fCaller := mocks.NewMockFacadeCaller(ctrl) - - resultSource := params.StringResults{ - Results: []params.StringResult{{ - Result: "bionic", - }}, - } - fCaller.EXPECT().FacadeCall(gomock.Any(), "TargetSeries", s.args, gomock.Any()).SetArg(3, resultSource) - - api := upgradeseries.NewStateFromCaller(fCaller, s.tag) - target, err := api.TargetSeries() - c.Assert(err, gc.IsNil) - c.Check(target, gc.Equals, "bionic") -} - func (s *upgradeSeriesSuite) TestUnitsPrepared(c *gc.C) { ctrl := gomock.NewController(c) defer ctrl.Finish() @@ -217,7 +180,7 @@ func (s *upgradeSeriesSuite) TestFinishUpgradeSeries(c *gc.C) { fCaller.EXPECT().FacadeCall(gomock.Any(), "FinishUpgradeSeries", args, gomock.Any()).SetArg(3, resultSource) api := upgradeseries.NewStateFromCaller(fCaller, s.tag) - err := api.FinishUpgradeSeries("xenial") + err := api.FinishUpgradeSeries(corebase.MustParseBaseFromString("ubuntu@16.04")) c.Assert(err, gc.IsNil) } diff --git a/api/facadeversions.go b/api/facadeversions.go index 12a1b2675963..049b08fa8076 100644 --- a/api/facadeversions.go +++ b/api/facadeversions.go @@ -126,7 +126,7 @@ var facadeVersions = facades.FacadeVersions{ "UnitAssigner": {1}, "Uniter": {19}, "Upgrader": {1}, - "UpgradeSeries": {3}, + "UpgradeSeries": {4}, "UpgradeSteps": {3}, "UserManager": {3}, "VolumeAttachmentsWatcher": {2}, diff --git a/api/package_test.go b/api/package_test.go index 8db928ff8920..0c4676b76438 100644 --- a/api/package_test.go +++ b/api/package_test.go @@ -41,6 +41,7 @@ func (*ImportSuite) TestImports(c *gc.C) { "core/model", "core/network", "core/os", + "core/os/ostype", "core/paths", "core/relation", "core/resources", diff --git a/apiserver/common/tools_test.go b/apiserver/common/tools_test.go index 3d6e15a339d0..18985a35c36b 100644 --- a/apiserver/common/tools_test.go +++ b/apiserver/common/tools_test.go @@ -22,6 +22,7 @@ import ( "github.com/juju/juju/core/arch" "github.com/juju/juju/core/network" coreos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs" "github.com/juju/juju/environs/config" envtools "github.com/juju/juju/environs/tools" @@ -132,7 +133,7 @@ func (s *getToolsSuite) TestOSTools(c *gc.C) { current := coretesting.CurrentVersion() currentCopy := current - currentCopy.Release = coretesting.HostSeries(c) + currentCopy.Release = "foo" configAttrs := map[string]interface{}{ "name": "some-name", "type": "some-type", @@ -475,7 +476,7 @@ func (s *findToolsSuite) TestFindToolsExactInStorage(c *gc.C) { {Version: "1.22.0-ubuntu-amd64"}, } s.PatchValue(&arch.HostArch, func() string { return arch.AMD64 }) - s.PatchValue(&coreos.HostOS, func() coreos.OSType { return coreos.Ubuntu }) + s.PatchValue(&coreos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) s.expectMatchingStorageTools(storageMetadata, nil) s.PatchValue(&jujuversion.Current, version.MustParseBinary("1.22-beta1-ubuntu-amd64").Number) diff --git a/apiserver/facades/agent/upgradeseries/register.go b/apiserver/facades/agent/upgradeseries/register.go index 6f5e56cee1b4..f76c460c12c8 100644 --- a/apiserver/facades/agent/upgradeseries/register.go +++ b/apiserver/facades/agent/upgradeseries/register.go @@ -15,7 +15,7 @@ import ( // Register is called to expose a package of facades onto a given registry. func Register(registry facade.FacadeRegistry) { - registry.MustRegister("UpgradeSeries", 3, func(stdCtx context.Context, ctx facade.ModelContext) (facade.Facade, error) { + registry.MustRegister("UpgradeSeries", 4, func(stdCtx context.Context, ctx facade.ModelContext) (facade.Facade, error) { return newAPI(ctx) // Adds SetStatus. }, reflect.TypeOf((*API)(nil))) } diff --git a/apiserver/facades/agent/upgradeseries/upgradeseries.go b/apiserver/facades/agent/upgradeseries/upgradeseries.go index 547b5273b1fb..905bbdc100e9 100644 --- a/apiserver/facades/agent/upgradeseries/upgradeseries.go +++ b/apiserver/facades/agent/upgradeseries/upgradeseries.go @@ -13,7 +13,6 @@ import ( "github.com/juju/juju/apiserver/common" apiservererrors "github.com/juju/juju/apiserver/errors" "github.com/juju/juju/apiserver/facade" - corebase "github.com/juju/juju/core/base" "github.com/juju/juju/core/model" "github.com/juju/juju/core/status" "github.com/juju/juju/rpc/params" @@ -118,65 +117,6 @@ func (a *API) SetMachineStatus(ctx context.Context, args params.UpgradeSeriesSta return result, nil } -// CurrentSeries returns what Juju thinks the current series of the machine is. -// Note that a machine could have been upgraded out-of-band by running -// do-release-upgrade outside of the upgrade-machine workflow, -// making this value incorrect. -func (a *API) CurrentSeries(ctx context.Context, args params.Entities) (params.StringResults, error) { - result := params.StringResults{} - - canAccess, err := a.AccessMachine() - if err != nil { - return result, err - } - - results := make([]params.StringResult, len(args.Entities)) - for i, entity := range args.Entities { - machine, err := a.authAndGetMachine(ctx, entity.Tag, canAccess) - if err != nil { - results[i].Error = apiservererrors.ServerError(err) - continue - } - series, err := corebase.GetSeriesFromChannel(machine.Base().OS, machine.Base().Channel) - if err != nil { - results[i].Error = apiservererrors.ServerError(err) - continue - } - results[i].Result = series - } - - result.Results = results - return result, nil -} - -// TargetSeries returns the series that a machine has been locked -// for upgrading to. -func (a *API) TargetSeries(ctx context.Context, args params.Entities) (params.StringResults, error) { - result := params.StringResults{} - - canAccess, err := a.AccessMachine() - if err != nil { - return result, err - } - - results := make([]params.StringResult, len(args.Entities)) - for i, entity := range args.Entities { - machine, err := a.authAndGetMachine(ctx, entity.Tag, canAccess) - if err != nil { - results[i].Error = apiservererrors.ServerError(err) - continue - } - target, err := machine.UpgradeSeriesTarget() - if err != nil { - results[i].Error = apiservererrors.ServerError(err) - } - results[i].Result = target - } - - result.Results = results - return result, nil -} - // StartUnitCompletion starts the upgrade series completion phase for all subordinate // units of a given machine. func (a *API) StartUnitCompletion(ctx context.Context, args params.UpgradeSeriesStartUnitCompletionParam) (params.ErrorResults, error) { diff --git a/apiserver/facades/agent/upgradeseries/upgradeseries_test.go b/apiserver/facades/agent/upgradeseries/upgradeseries_test.go index 0d3d479cf743..399264dd81c6 100644 --- a/apiserver/facades/agent/upgradeseries/upgradeseries_test.go +++ b/apiserver/facades/agent/upgradeseries/upgradeseries_test.go @@ -89,30 +89,6 @@ func (s *upgradeSeriesSuite) TestSetMachineStatus(c *gc.C) { }) } -func (s *upgradeSeriesSuite) TestCurrentSeries(c *gc.C) { - defer s.arrangeTest(c).Finish() - - s.machine.EXPECT().Base().Return(state.UbuntuBase("16.04")).AnyTimes() - - results, err := s.api.CurrentSeries(context.Background(), s.entityArgs) - c.Assert(err, jc.ErrorIsNil) - c.Assert(results, gc.DeepEquals, params.StringResults{ - Results: []params.StringResult{{Result: "xenial"}}, - }) -} - -func (s *upgradeSeriesSuite) TestUpgradeSeriesTarget(c *gc.C) { - defer s.arrangeTest(c).Finish() - - s.machine.EXPECT().UpgradeSeriesTarget().Return("bionic", nil) - - results, err := s.api.TargetSeries(context.Background(), s.entityArgs) - c.Assert(err, jc.ErrorIsNil) - c.Assert(results, gc.DeepEquals, params.StringResults{ - Results: []params.StringResult{{Result: "bionic"}}, - }) -} - func (s *upgradeSeriesSuite) TestStartUnitCompletion(c *gc.C) { defer s.arrangeTest(c).Finish() diff --git a/apiserver/facades/client/application/deploy_test.go b/apiserver/facades/client/application/deploy_test.go index 790093f57851..de2abfc52e57 100644 --- a/apiserver/facades/client/application/deploy_test.go +++ b/apiserver/facades/client/application/deploy_test.go @@ -98,7 +98,7 @@ func (s *DeployLocalSuite) TestDeployMinimal(c *gc.C) { c.Assert(err, jc.ErrorIsNil) s.assertCharm(c, app, s.charm.URL()) s.assertSettings(c, app, charm.Settings{}) - s.assertApplicationConfig(c, app, coreconfig.ConfigAttributes(nil)) + s.assertApplicationConfig(c, app, coreconfig.ConfigAttributes{}) s.assertConstraints(c, app, constraints.MustParse("arch=amd64")) s.assertMachines(c, app, constraints.Value{}) } diff --git a/apiserver/facades/client/client/client_test.go b/apiserver/facades/client/client/client_test.go index 968f2b633863..01f1396bee5d 100644 --- a/apiserver/facades/client/client/client_test.go +++ b/apiserver/facades/client/client/client_test.go @@ -28,6 +28,7 @@ import ( "github.com/juju/juju/core/model" "github.com/juju/juju/core/multiwatcher" coreos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/core/permission" "github.com/juju/juju/core/status" "github.com/juju/juju/domain/access/service" @@ -477,7 +478,7 @@ func (s *findToolsSuite) TestFindToolsCAASReleased(c *gc.C) { {Version: version.MustParseBinary("2.9.10-ubuntu-amd64")}, {Version: version.MustParseBinary("2.9.11-ubuntu-amd64")}, } - s.PatchValue(&coreos.HostOS, func() coreos.OSType { return coreos.Ubuntu }) + s.PatchValue(&coreos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) gomock.InOrder( authorizer.EXPECT().AuthClient().Return(true), @@ -562,7 +563,7 @@ func (s *findToolsSuite) TestFindToolsCAASNonReleased(c *gc.C) { {Version: version.MustParseBinary("2.9.11-ubuntu-amd64")}, {Version: version.MustParseBinary("2.9.12-ubuntu-amd64")}, } - s.PatchValue(&coreos.HostOS, func() coreos.OSType { return coreos.Ubuntu }) + s.PatchValue(&coreos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) gomock.InOrder( authorizer.EXPECT().AuthClient().Return(true), diff --git a/apiserver/facades/client/modelupgrader/upgrader_test.go b/apiserver/facades/client/modelupgrader/upgrader_test.go index d88abcf1ae40..eda1ad29e744 100644 --- a/apiserver/facades/client/modelupgrader/upgrader_test.go +++ b/apiserver/facades/client/modelupgrader/upgrader_test.go @@ -22,6 +22,7 @@ import ( apiservertesting "github.com/juju/juju/apiserver/testing" "github.com/juju/juju/controller" coreos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs" environscloudspec "github.com/juju/juju/environs/cloudspec" envtools "github.com/juju/juju/environs/tools" @@ -784,7 +785,7 @@ func (s *modelUpgradeSuite) TestFindToolsCAASReleased(c *gc.C) { {Version: version.MustParseBinary("2.9.10-ubuntu-amd64")}, {Version: version.MustParseBinary("2.9.11-ubuntu-amd64")}, } - s.PatchValue(&coreos.HostOS, func() coreos.OSType { return coreos.Ubuntu }) + s.PatchValue(&coreos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) gomock.InOrder( s.toolsFinder.EXPECT().FindAgents( @@ -831,7 +832,7 @@ func (s *modelUpgradeSuite) TestFindToolsCAASReleasedExact(c *gc.C) { simpleStreams := []*coretools.Tools{ {Version: version.MustParseBinary("2.9.10-ubuntu-amd64")}, } - s.PatchValue(&coreos.HostOS, func() coreos.OSType { return coreos.Ubuntu }) + s.PatchValue(&coreos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) gomock.InOrder( s.toolsFinder.EXPECT().FindAgents(gomock.Any(), @@ -874,7 +875,7 @@ func (s *modelUpgradeSuite) TestFindToolsCAASNonReleased(c *gc.C) { {Version: version.MustParseBinary("2.9.11-ubuntu-amd64")}, {Version: version.MustParseBinary("2.9.12-ubuntu-amd64")}, } - s.PatchValue(&coreos.HostOS, func() coreos.OSType { return coreos.Ubuntu }) + s.PatchValue(&coreos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) gomock.InOrder( s.toolsFinder.EXPECT().FindAgents(gomock.Any(), common.FindAgentsParams{ diff --git a/apiserver/facades/schema.json b/apiserver/facades/schema.json index 574c12ca6909..5e5acf8ccb2e 100644 --- a/apiserver/facades/schema.json +++ b/apiserver/facades/schema.json @@ -44985,7 +44985,7 @@ { "Name": "UpgradeSeries", "Description": "API serves methods required by the machine agent upgrade-machine worker.", - "Version": 3, + "Version": 4, "AvailableTo": [ "controller-machine-agent", "machine-agent", @@ -44995,18 +44995,6 @@ "Schema": { "type": "object", "properties": { - "CurrentSeries": { - "type": "object", - "properties": { - "Params": { - "$ref": "#/definitions/Entities" - }, - "Result": { - "$ref": "#/definitions/StringResults" - } - }, - "description": "CurrentSeries returns what Juju thinks the current series of the machine is.\nNote that a machine could have been upgraded out-of-band by running\ndo-release-upgrade outside of the upgrade-machine workflow,\nmaking this value incorrect." - }, "FinishUpgradeSeries": { "type": "object", "properties": { @@ -45097,18 +45085,6 @@ }, "description": "StartUnitCompletion starts the upgrade series completion phase for all subordinate\nunits of a given machine." }, - "TargetSeries": { - "type": "object", - "properties": { - "Params": { - "$ref": "#/definitions/Entities" - }, - "Result": { - "$ref": "#/definitions/StringResults" - } - }, - "description": "TargetSeries returns the series that a machine has been locked\nfor upgrading to." - }, "UnitsCompleted": { "type": "object", "properties": { @@ -45402,36 +45378,6 @@ "entities" ] }, - "StringResult": { - "type": "object", - "properties": { - "error": { - "$ref": "#/definitions/Error" - }, - "result": { - "type": "string" - } - }, - "additionalProperties": false, - "required": [ - "result" - ] - }, - "StringResults": { - "type": "object", - "properties": { - "results": { - "type": "array", - "items": { - "$ref": "#/definitions/StringResult" - } - } - }, - "additionalProperties": false, - "required": [ - "results" - ] - }, "UpdateChannelArg": { "type": "object", "properties": { diff --git a/caas/kubernetes/provider/application/constraints.go b/caas/kubernetes/provider/application/constraints.go index b3120f7c45f9..68450f3d13c8 100644 --- a/caas/kubernetes/provider/application/constraints.go +++ b/caas/kubernetes/provider/application/constraints.go @@ -159,13 +159,15 @@ func processNodeAffinity(pod *core.PodSpec, affinityLabels map[string]string) er } var nodeSelectorTerm core.NodeSelectorTerm updateSelectorTerms(&nodeSelectorTerm, affinityTags) - if pod.Affinity == nil { - pod.Affinity = &core.Affinity{} - } - pod.Affinity.NodeAffinity = &core.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{ - NodeSelectorTerms: []core.NodeSelectorTerm{nodeSelectorTerm}, - }, + if len(nodeSelectorTerm.MatchExpressions) > 0 { + if pod.Affinity == nil { + pod.Affinity = &core.Affinity{} + } + pod.Affinity.NodeAffinity = &core.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{ + NodeSelectorTerms: []core.NodeSelectorTerm{nodeSelectorTerm}, + }, + } } return nil } @@ -240,12 +242,12 @@ func processPodAffinity(pod *core.PodSpec, affinityLabels map[string]string) err affinityTerm.TopologyKey = topologyKey } } - if pod.Affinity == nil { - pod.Affinity = &core.Affinity{} - } var affinityTerm core.PodAffinityTerm updateAffinityTerm(&affinityTerm, affinityTags) if len(affinityTerm.LabelSelector.MatchExpressions) > 0 || affinityTerm.TopologyKey != "" { + if pod.Affinity == nil { + pod.Affinity = &core.Affinity{} + } pod.Affinity.PodAffinity = &core.PodAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []core.PodAffinityTerm{affinityTerm}, } @@ -254,6 +256,9 @@ func processPodAffinity(pod *core.PodSpec, affinityLabels map[string]string) err var antiAffinityTerm core.PodAffinityTerm updateAffinityTerm(&antiAffinityTerm, antiAffinityTags) if len(antiAffinityTerm.LabelSelector.MatchExpressions) > 0 || antiAffinityTerm.TopologyKey != "" { + if pod.Affinity == nil { + pod.Affinity = &core.Affinity{} + } pod.Affinity.PodAntiAffinity = &core.PodAntiAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []core.PodAffinityTerm{antiAffinityTerm}, } diff --git a/caas/kubernetes/provider/application/constraints_test.go b/caas/kubernetes/provider/application/constraints_test.go index ce39bb93c582..814e9a2863f2 100644 --- a/caas/kubernetes/provider/application/constraints_test.go +++ b/caas/kubernetes/provider/application/constraints_test.go @@ -69,6 +69,8 @@ func (s *applyConstraintsSuite) TestPodAffinityJustTopologyKey(c *gc.C) { TopologyKey: "foo", }}, }) + c.Assert(pod.Affinity.PodAntiAffinity, gc.IsNil) + c.Assert(pod.Affinity.NodeAffinity, gc.IsNil) } func (s *applyConstraintsSuite) TestAffinityPod(c *gc.C) { @@ -94,6 +96,8 @@ func (s *applyConstraintsSuite) TestAffinityPod(c *gc.C) { }, }}, }) + c.Assert(pod.Affinity.PodAntiAffinity, gc.IsNil) + c.Assert(pod.Affinity.NodeAffinity, gc.IsNil) } func (s *applyConstraintsSuite) TestPodAffinityAll(c *gc.C) { @@ -135,6 +139,8 @@ func (s *applyConstraintsSuite) TestAntiPodAffinityJustTopologyKey(c *gc.C) { TopologyKey: "foo", }}, }) + c.Assert(pod.Affinity.PodAffinity, gc.IsNil) + c.Assert(pod.Affinity.NodeAffinity, gc.IsNil) } func (s *applyConstraintsSuite) TestAntiPodAffinity(c *gc.C) { @@ -160,6 +166,8 @@ func (s *applyConstraintsSuite) TestAntiPodAffinity(c *gc.C) { }, }}, }) + c.Assert(pod.Affinity.PodAffinity, gc.IsNil) + c.Assert(pod.Affinity.NodeAffinity, gc.IsNil) } func (s *applyConstraintsSuite) TestAntiPodAffinityAll(c *gc.C) { @@ -186,6 +194,8 @@ func (s *applyConstraintsSuite) TestAntiPodAffinityAll(c *gc.C) { TopologyKey: "foo", }}, }) + c.Assert(pod.Affinity.PodAffinity, gc.IsNil) + c.Assert(pod.Affinity.NodeAffinity, gc.IsNil) } func (s *applyConstraintsSuite) TestNodeAntiAffinity(c *gc.C) { @@ -210,4 +220,6 @@ func (s *applyConstraintsSuite) TestNodeAntiAffinity(c *gc.C) { }}, }, }) + c.Assert(pod.Affinity.PodAffinity, gc.IsNil) + c.Assert(pod.Affinity.PodAntiAffinity, gc.IsNil) } diff --git a/cmd/containeragent/initialize/package_test.go b/cmd/containeragent/initialize/package_test.go index ec62ad315417..f42768f6ad5c 100644 --- a/cmd/containeragent/initialize/package_test.go +++ b/cmd/containeragent/initialize/package_test.go @@ -63,6 +63,7 @@ func (*importSuite) TestImports(c *gc.C) { "core/network", "core/objectstore", "core/os", + "core/os/ostype", "core/output", "core/paths", "core/permission", diff --git a/cmd/internal/run/run.go b/cmd/internal/run/run.go index d94b452bd48c..ce3e50cc8748 100644 --- a/cmd/internal/run/run.go +++ b/cmd/internal/run/run.go @@ -28,6 +28,7 @@ import ( jujucmd "github.com/juju/juju/cmd" "github.com/juju/juju/core/machinelock" jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/core/paths" "github.com/juju/juju/internal/worker/uniter" "github.com/juju/juju/juju/sockets" @@ -335,7 +336,7 @@ func (c *RunCommand) executeInUnitContext() (*exec.ExecResponse, error) { // will work on most GNU/Linux systems. func (c *RunCommand) appendProxyToCommands() string { switch jujuos.HostOS() { - case jujuos.Ubuntu: + case ostype.Ubuntu: return `[ -f "/home/ubuntu/.juju-proxy" ] && . "/home/ubuntu/.juju-proxy"` + "\n" + c.commands default: return c.commands diff --git a/cmd/juju/commands/bootstrap_test.go b/cmd/juju/commands/bootstrap_test.go index d5e3e39cd171..eed274cfc26e 100644 --- a/cmd/juju/commands/bootstrap_test.go +++ b/cmd/juju/commands/bootstrap_test.go @@ -37,6 +37,7 @@ import ( "github.com/juju/juju/core/constraints" "github.com/juju/juju/core/model" coreos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs" "github.com/juju/juju/environs/bootstrap" "github.com/juju/juju/environs/config" @@ -134,7 +135,7 @@ func (s *BootstrapSuite) SetUpTest(c *gc.C) { // override this. s.PatchValue(&jujuversion.Current, v100u64.Number) s.PatchValue(&arch.HostArch, func() string { return v100u64.Arch }) - s.PatchValue(&coreos.HostOS, func() coreos.OSType { return coreos.Ubuntu }) + s.PatchValue(&coreos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) s.PatchValue(&corebase.UbuntuDistroInfo, "/path/notexists") // Ensure KUBECONFIG doesn't interfere with tests. @@ -1607,7 +1608,7 @@ func (s *BootstrapSuite) TestBootstrapWithNoBootstrapSeriesUsesFallbackButStillF _, err := cmdtesting.RunCommand( c, s.newBootstrapCommand(), "no-cloud-regions", "ctrl", "--config", "default-base=spock", ) - c.Assert(err, gc.ErrorMatches, `invalid default base "spock".*`) + c.Assert(err, gc.ErrorMatches, `series "spock" not valid`) } func (s *BootstrapSuite) TestBootstrapBaseWithNoBootstrapSeriesUsesFallbackButStillFails(c *gc.C) { diff --git a/cmd/juju/commands/main_test.go b/cmd/juju/commands/main_test.go index 8aa6872f3a41..1e0c06085128 100644 --- a/cmd/juju/commands/main_test.go +++ b/cmd/juju/commands/main_test.go @@ -26,6 +26,7 @@ import ( "github.com/juju/juju/cmd/juju/cloud" "github.com/juju/juju/cmd/modelcmd" jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/juju/osenv" "github.com/juju/juju/jujuclient/jujuclienttesting" "github.com/juju/juju/testing" @@ -214,7 +215,7 @@ func (s *MainSuite) TestActualRunJujuArgOrder(c *gc.C) { func (s *MainSuite) TestNoWarn2xFirstRun(c *gc.C) { // Code should only rnu on ubuntu series, so patch out the series for // when non-ubuntu OSes run this test. - s.PatchValue(&jujuos.HostOS, func() jujuos.OSType { return jujuos.Ubuntu }) + s.PatchValue(&jujuos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) argChan := make(chan []string, 1) // we shouldn't actually be running anything, but if we do, this will diff --git a/core/base/package_test.go b/core/base/package_test.go index 733a58a4bcef..b810cda6c466 100644 --- a/core/base/package_test.go +++ b/core/base/package_test.go @@ -25,6 +25,6 @@ var _ = gc.Suite(&ImportTest{}) func (*ImportTest) TestImports(c *gc.C) { found := coretesting.FindJujuCoreImports(c, "github.com/juju/juju/core/base") c.Assert(found, jc.SameContents, []string{ - "core/os", + "core/os/ostype", }) } diff --git a/core/base/supportedseries.go b/core/base/supportedseries.go index 55b2f05b8f39..0faffd965fb4 100644 --- a/core/base/supportedseries.go +++ b/core/base/supportedseries.go @@ -14,7 +14,7 @@ import ( jujuos "github.com/juju/os/v2" "github.com/juju/os/v2/series" - coreos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" ) const ( @@ -105,9 +105,9 @@ func getAllSeriesVersions() map[SeriesName]seriesVersion { // GetOSFromSeries will return the operating system based // on the series that is passed to it -func GetOSFromSeries(series string) (coreos.OSType, error) { +func GetOSFromSeries(series string) (ostype.OSType, error) { if series == "" { - return coreos.Unknown, errors.NotValidf("series %q", series) + return ostype.Unknown, errors.NotValidf("series %q", series) } seriesVersionsMutex.Lock() @@ -128,7 +128,7 @@ func GetOSFromSeries(series string) (coreos.OSType, error) { func DefaultOSTypeNameFromSeries(series string) string { osType, err := GetOSFromSeries(series) if err != nil { - osType = coreos.Ubuntu + osType = ostype.Ubuntu } return strings.ToLower(osType.String()) } @@ -248,18 +248,18 @@ func ubuntuVersions( return save } -func getOSFromSeries(series SeriesName) (coreos.OSType, error) { +func getOSFromSeries(series SeriesName) (ostype.OSType, error) { if _, ok := ubuntuSeries[series]; ok { - return coreos.Ubuntu, nil + return ostype.Ubuntu, nil } if _, ok := centosSeries[series]; ok { - return coreos.CentOS, nil + return ostype.CentOS, nil } if series == genericLinuxSeries { - return coreos.GenericLinux, nil + return ostype.GenericLinux, nil } - return coreos.Unknown, errors.Trace(unknownOSForSeriesError(series)) + return ostype.Unknown, errors.Trace(unknownOSForSeriesError(series)) } var ( diff --git a/core/base/supportedseries_test.go b/core/base/supportedseries_test.go index e0023fbd6777..cee5d5158ca5 100644 --- a/core/base/supportedseries_test.go +++ b/core/base/supportedseries_test.go @@ -11,7 +11,7 @@ import ( jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" - coreos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" ) const distroInfoContents = `version,codename,series,created,release,eol,eol-server @@ -92,17 +92,17 @@ func (s *SupportedSeriesSuite) TestSeriesForTypesUsingInvalidSeries(c *gc.C) { var getOSFromSeriesTests = []struct { series string - want coreos.OSType + want ostype.OSType err string }{{ series: "precise", - want: coreos.Ubuntu, + want: ostype.Ubuntu, }, { series: "centos7", - want: coreos.CentOS, + want: ostype.CentOS, }, { series: "genericlinux", - want: coreos.GenericLinux, + want: ostype.GenericLinux, }, { series: "", err: "series \"\" not valid", diff --git a/core/os/base.go b/core/os/base.go new file mode 100644 index 000000000000..8515010696da --- /dev/null +++ b/core/os/base.go @@ -0,0 +1,35 @@ +// Copyright 2024 Canonical Ltd. +// Licensed under the LGPLv3, see LICENCE file for details. + +package os + +import ( + "sync" + + "github.com/juju/errors" + + corebase "github.com/juju/juju/core/base" +) + +var ( + // HostBase returns the base of the machine the current process is + // running on (overrideable var for testing) + HostBase func() (corebase.Base, error) = hostBase + + baseOnce sync.Once + + // These are filled in by the first call to hostBase + base corebase.Base + baseErr error +) + +func hostBase() (corebase.Base, error) { + var err error + baseOnce.Do(func() { + base, err = readBase() + if err != nil { + baseErr = errors.Annotate(err, "cannot determine host base") + } + }) + return base, baseErr +} diff --git a/core/os/base_darwin.go b/core/os/base_darwin.go new file mode 100644 index 000000000000..111b6c7193fd --- /dev/null +++ b/core/os/base_darwin.go @@ -0,0 +1,22 @@ +// Copyright 2024 Canonical Ltd. +// Licensed under the LGPLv3, see LICENCE file for details. + +package os + +import ( + "syscall" + + corebase "github.com/juju/juju/core/base" +) + +var sysctlVersion = func() (string, error) { + return syscall.Sysctl("kern.osrelease") +} + +func readBase() (corebase.Base, error) { + channel, err := sysctlVersion() + if err != nil { + return corebase.Base{}, err + } + return corebase.ParseBase("osx", channel) +} diff --git a/core/os/base_darwin_test.go b/core/os/base_darwin_test.go new file mode 100644 index 000000000000..2bf8c237c0f3 --- /dev/null +++ b/core/os/base_darwin_test.go @@ -0,0 +1,32 @@ +// Copyright 2024 Canonical Ltd. +// Licensed under the LGPLv3, see LICENCE file for details. + +package os + +import ( + "github.com/juju/testing" + jc "github.com/juju/testing/checkers" + gc "gopkg.in/check.v1" + + corebase "github.com/juju/juju/core/base" +) + +type macOSXSeriesSuite struct { + testing.CleanupSuite +} + +var _ = gc.Suite(&macOSXSeriesSuite{}) + +func (*macOSXSeriesSuite) TestGetSysctlVersionPlatform(c *gc.C) { + // Test that sysctlVersion returns something that looks like a dotted revision number + releaseVersion, err := sysctlVersion() + c.Assert(err, jc.ErrorIsNil) + c.Check(releaseVersion, gc.Matches, `\d+\..*`) +} + +func (s *macOSXSeriesSuite) TestOSVersion(c *gc.C) { + s.PatchValue(&sysctlVersion, func() (string, error) { return "23.1.0", nil }) + b, err := readBase() + c.Assert(err, jc.ErrorIsNil) + c.Assert(b, gc.Equals, corebase.MustParseBaseFromString("osx@23.1.0")) +} diff --git a/core/os/base_linux.go b/core/os/base_linux.go new file mode 100644 index 000000000000..4d7fd2dfc8d6 --- /dev/null +++ b/core/os/base_linux.go @@ -0,0 +1,16 @@ +// Copyright 2024 Canonical Ltd. +// Licensed under the LGPLv3, see LICENCE file for details. + +package os + +import ( + corebase "github.com/juju/juju/core/base" +) + +func readBase() (corebase.Base, error) { + values, err := ReadOSRelease(osReleaseFile) + if err != nil { + return corebase.Base{}, err + } + return corebase.ParseBase(values["ID"], values["VERSION_ID"]) +} diff --git a/core/os/base_linux_test.go b/core/os/base_linux_test.go new file mode 100644 index 000000000000..0e622a48c426 --- /dev/null +++ b/core/os/base_linux_test.go @@ -0,0 +1,136 @@ +// Copyright 2024 Canonical Ltd. +// Licensed under the LGPLv3, see LICENCE file for details. + +package os + +import ( + "io/ioutil" + "path/filepath" + + "github.com/juju/testing" + jc "github.com/juju/testing/checkers" + gc "gopkg.in/check.v1" + + corebase "github.com/juju/juju/core/base" +) + +type linuxBaseSuite struct { + testing.CleanupSuite +} + +var _ = gc.Suite(&linuxBaseSuite{}) + +var readBaseTests = []struct { + contents string + base corebase.Base + err string +}{{ + `NAME="Ubuntu" +VERSION="99.04 LTS, Star Trek" +ID=ubuntu +ID_LIKE=debian +PRETTY_NAME="Ubuntu spock (99.04 LTS)" +VERSION_ID="99.04" +`, + corebase.MustParseBaseFromString("ubuntu@99.04"), + "", +}, { + `NAME="Ubuntu" +VERSION="12.04.5 LTS, Precise Pangolin" +ID=ubuntu +ID_LIKE=debian +PRETTY_NAME="Ubuntu precise (12.04.5 LTS)" +VERSION_ID="12.04" +`, + corebase.MustParseBaseFromString("ubuntu@12.04"), + "", +}, { + `NAME="Ubuntu" +ID=ubuntu +VERSION_ID= "12.04" `, + corebase.MustParseBaseFromString("ubuntu@12.04"), + "", +}, { + `NAME='Ubuntu' +ID='ubuntu' +VERSION_ID='12.04' +`, + + corebase.MustParseBaseFromString("ubuntu@12.04"), + "", +}, { + `NAME="CentOS Linux" +ID="centos" +VERSION_ID="7" +`, + corebase.MustParseBaseFromString("centos@7"), + "", +}, { + `NAME="openSUSE Leap" +ID=opensuse +VERSION_ID="42.2" +`, + corebase.MustParseBaseFromString("opensuse@42.2"), + "", +}, { + `NAME="Ubuntu" +VERSION="14.04.1 LTS, Trusty Tahr" +ID=ubuntu +ID_LIKE=debian +PRETTY_NAME="Ubuntu 14.04.1 LTS" +VERSION_ID="14.04" +HOME_URL="http://www.ubuntu.com/" +SUPPORT_URL="http://help.ubuntu.com/" +BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/" +`, + corebase.MustParseBaseFromString("ubuntu@14.04"), + "", +}, { + `NAME=Fedora +VERSION="24 (Twenty Four)" +ID=fedora +VERSION_ID=24 +PRETTY_NAME="Fedora 24 (Twenty Four)" +CPE_NAME="cpe:/o:fedoraproject:fedora:24" +HOME_URL="https://fedoraproject.org/" +BUG_REPORT_URL="https://bugzilla.redhat.com/" +`, + corebase.MustParseBaseFromString("fedora@24"), + "", +}, { + + "", + corebase.Base{}, + "OS release file is missing ID", +}, { + `NAME="CentOS Linux" +ID="centos" +`, + corebase.Base{}, + "OS release file is missing VERSION_ID", +}, { + `NAME=openSUSE +ID=opensuse +VERSION_ID="42.3"`, + corebase.MustParseBaseFromString("opensuse@42.3"), + "", +}, +} + +func (s *linuxBaseSuite) TestReadSeries(c *gc.C) { + d := c.MkDir() + f := filepath.Join(d, "foo") + s.PatchValue(&osReleaseFile, f) + for i, t := range readBaseTests { + c.Logf("test %d", i) + err := ioutil.WriteFile(f, []byte(t.contents), 0666) + c.Assert(err, jc.ErrorIsNil) + b, err := readBase() + if t.err == "" { + c.Assert(err, jc.ErrorIsNil) + c.Assert(b, gc.Equals, t.base) + } else { + c.Assert(err, gc.ErrorMatches, t.err) + } + } +} diff --git a/core/os/base_test.go b/core/os/base_test.go new file mode 100644 index 000000000000..3a0d20f47f71 --- /dev/null +++ b/core/os/base_test.go @@ -0,0 +1,31 @@ +// Copyright 2024 Canonical Ltd. +// Licensed under the LGPLv3, see LICENCE file for details. + +package os_test + +import ( + "github.com/juju/testing" + jc "github.com/juju/testing/checkers" + gc "gopkg.in/check.v1" + + corebase "github.com/juju/juju/core/base" + "github.com/juju/juju/core/os" +) + +type baseSuite struct { + testing.CleanupSuite +} + +var _ = gc.Suite(&baseSuite{}) + +var b = corebase.Base{OS: "freelunch", Channel: corebase.Channel{Track: "0"}} + +func (s *baseSuite) TestHostBaseOverride(c *gc.C) { + // Really just tests that HostBase is overridable + s.PatchValue(&os.HostBase, func() (corebase.Base, error) { + return b, nil + }) + ser, err := os.HostBase() + c.Assert(err, jc.ErrorIsNil) + c.Assert(ser, gc.Equals, b) +} diff --git a/core/os/base_windows.go b/core/os/base_windows.go new file mode 100644 index 000000000000..e4aef9e9a414 --- /dev/null +++ b/core/os/base_windows.go @@ -0,0 +1,134 @@ +// Copyright 2024 Canonical Ltd. +// Licensed under the LGPLv3, see LICENCE file for details. + +package os + +import ( + "os" + "strings" + + "github.com/juju/errors" + "golang.org/x/sys/windows/registry" + + corebase "github.com/juju/juju/core/base" +) + +var ( + // currentVersionKey is defined as a variable instead of a constant + // to allow overwriting during testing + currentVersionKey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion" + + // isNanoKey determines the registry key that can be queried to determine whether + // a machine is a nano machine + isNanoKey = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Server\\ServerLevels" + + // Windows versions come in various flavors: + // Standard, Datacenter, etc. We use string prefix match them to one + // of the following. Specify the longest name in a particular series first + // For example, if we have "Win 2012" and "Win 2012 R2", we specify "Win 2012 R2" first. + // We need to make sure we manually update this list with each new windows release. + windowsVersionMatchOrder = []string{ + "Hyper-V Server 2012 R2", + "Hyper-V Server 2012", + "Windows Server 2008 R2", + "Windows Server 2012 R2", + "Windows Server 2012", + "Hyper-V Server 2016", + "Windows Server 2016", + "Windows Server 2019", + "Windows Storage Server 2012 R2", + "Windows Storage Server 2012", + "Windows Storage Server 2016", + "Windows 7", + "Windows 8.1", + "Windows 8", + "Windows 10", + "Windows 11", + } + + // windowsVersions is a mapping consisting of the output from + // the following WMI query: (gwmi Win32_OperatingSystem).Name + windowsVersions = map[string]string{ + "Hyper-V Server 2012 R2": "2012hvr2", + "Hyper-V Server 2012": "2012hv", + "Windows Server 2008 R2": "2008r2", + "Windows Server 2012 R2": "2012r2", + "Windows Server 2012": "2012", + "Hyper-V Server 2016": "2016hv", + "Windows Server 2016": "2016", + "Windows Server 2019": "2019", + "Windows Storage Server 2012 R2": "2012r2", + "Windows Storage Server 2012": "2012", + "Windows Storage Server 2016": "2016", + "Windows Storage Server 2019": "2019", + "Windows 7": "7", + "Windows 8.1": "81", + "Windows 8": "8", + "Windows 10": "10", + "Windows 11": "11", + } + + // windowsNanoVersions is a mapping from the product name + // stored in registry to a juju defined nano-series + // On the nano version so far the product name actually + // is identical to the correspondent main windows version + // and the information about it being nano is stored in + // a different place. + windowsNanoVersions = map[string]string{ + "Windows Server 2016": "2016nano", + } +) + +func getVersionFromRegistry() (string, error) { + k, err := registry.OpenKey(registry.LOCAL_MACHINE, currentVersionKey, registry.QUERY_VALUE) + if err != nil { + return "", errors.Trace(err) + } + defer k.Close() + s, _, err := k.GetStringValue("ProductName") + if err != nil { + return "", errors.Trace(err) + } + + return s, nil +} + +func readBase() (corebase.Base, error) { + ver, err := getVersionFromRegistry() + if err != nil { + return corebase.Base{}, errors.Trace(err) + } + + var lookAt = windowsVersions + + isNano, err := isWindowsNano() + if err != nil && os.IsNotExist(err) { + return corebase.Base{}, errors.Trace(err) + } + if isNano { + lookAt = windowsNanoVersions + } + + for _, value := range windowsVersionMatchOrder { + if strings.HasPrefix(ver, value) { + if val, ok := lookAt[value]; ok { + return corebase.ParseBase("win", val) + } + } + } + return corebase.Base{}, errors.Errorf("unknown series %q", ver) +} + +func isWindowsNano() (bool, error) { + k, err := registry.OpenKey(registry.LOCAL_MACHINE, isNanoKey, registry.QUERY_VALUE) + if err != nil { + return false, errors.Trace(err) + } + defer k.Close() + + s, _, err := k.GetIntegerValue("NanoServer") + if err != nil { + return false, errors.Trace(err) + } + return s == 1, nil +} diff --git a/core/os/base_windows_test.go b/core/os/base_windows_test.go new file mode 100644 index 000000000000..b0c3781428fe --- /dev/null +++ b/core/os/base_windows_test.go @@ -0,0 +1,185 @@ +// Copyright 2024 Canonical Ltd. +// Licensed under the LGPLv3, see LICENCE file for details. + +package os + +import ( + "crypto/rand" + "encoding/base64" + "fmt" + "io" + + "github.com/juju/testing" + jc "github.com/juju/testing/checkers" + "golang.org/x/sys/windows/registry" + gc "gopkg.in/check.v1" + + corebase "github.com/juju/juju/core/base" +) + +const randomPasswordBytes = 18 + +type windowsBaseSuite struct { + testing.CleanupSuite +} + +var versionTests = []struct { + version string + want corebase.Base +}{ + { + "Hyper-V Server 2012 R2", + corebase.MustParseBaseFromString("win@2012hvr2"), + }, + { + "Hyper-V Server 2012", + corebase.MustParseBaseFromString("win@2012hv"), + }, + { + "Windows Server 2008 R2", + corebase.MustParseBaseFromString("win@2008r2"), + }, + { + "Windows Server 2012 R2", + corebase.MustParseBaseFromString("win@2012r2"), + }, + { + "Windows Server 2012", + corebase.MustParseBaseFromString("win@2012"), + }, + { + "Windows Server 2012 R2 Datacenter", + corebase.MustParseBaseFromString("win@2012r2"), + }, + { + "Windows Server 2012 Standard", + corebase.MustParseBaseFromString("win@2012"), + }, + { + "Windows Storage Server 2012 R2", + corebase.MustParseBaseFromString("win@2012r2"), + }, + { + "Windows Storage Server 2012 Standard", + corebase.MustParseBaseFromString("win@2012"), + }, + { + "Windows Storage Server 2012 R2 Standard", + corebase.MustParseBaseFromString("win@2012r2"), + }, + { + "Windows 7 Home", + corebase.MustParseBaseFromString("win@7"), + }, + { + "Windows 8 Pro", + corebase.MustParseBaseFromString("win@8"), + }, + { + "Windows 8.1 Pro", + corebase.MustParseBaseFromString("win@81"), + }, +} + +func (s *windowsBaseSuite) SetUpTest(c *gc.C) { + s.CleanupSuite.SetUpTest(c) + s.createRegKey(c, ¤tVersionKey) +} + +func (s *windowsBaseSuite) createRegKey(c *gc.C, key *string) { + salt, err := RandomPassword() + c.Assert(err, jc.ErrorIsNil) + regKey := fmt.Sprintf(`SOFTWARE\JUJU\%s`, salt) + s.PatchValue(key, regKey) + + k, _, err := registry.CreateKey(registry.LOCAL_MACHINE, *key, registry.ALL_ACCESS) + c.Assert(err, jc.ErrorIsNil) + + err = k.Close() + c.Assert(err, jc.ErrorIsNil) + + s.AddCleanup(func(*gc.C) { + registry.DeleteKey(registry.LOCAL_MACHINE, currentVersionKey) + }) +} + +func (s *windowsBaseSuite) TestReadBase(c *gc.C) { + for _, value := range versionTests { + k, err := registry.OpenKey(registry.LOCAL_MACHINE, currentVersionKey, registry.ALL_ACCESS) + c.Assert(err, jc.ErrorIsNil) + + err = k.SetStringValue("ProductName", value.version) + c.Assert(err, jc.ErrorIsNil) + + err = k.Close() + c.Assert(err, jc.ErrorIsNil) + + ver, err := readBase() + c.Assert(err, jc.ErrorIsNil) + c.Assert(ver, gc.Equals, value.want) + } +} + +type windowsNanoBaseSuite struct { + windowsBaseSuite +} + +var _ = gc.Suite(&windowsNanoBaseSuite{}) + +func (s *windowsNanoBaseSuite) SetUpTest(c *gc.C) { + s.windowsBaseSuite.SetUpTest(c) + s.createRegKey(c, &isNanoKey) + + k, err := registry.OpenKey(registry.LOCAL_MACHINE, isNanoKey, registry.ALL_ACCESS) + c.Assert(err, jc.ErrorIsNil) + + err = k.SetDWordValue("NanoServer", 1) + c.Assert(err, jc.ErrorIsNil) + + err = k.Close() + c.Assert(err, jc.ErrorIsNil) +} + +var nanoVersionTests = []struct { + version string + want corebase.Base +}{{ + "Windows Server 2016", + corebase.MustParseBaseFromString("win@2016nano"), +}} + +func (s *windowsNanoBaseSuite) TestReadBase(c *gc.C) { + for _, value := range nanoVersionTests { + k, err := registry.OpenKey(registry.LOCAL_MACHINE, currentVersionKey, registry.ALL_ACCESS) + c.Assert(err, jc.ErrorIsNil) + + err = k.SetStringValue("ProductName", value.version) + c.Assert(err, jc.ErrorIsNil) + + err = k.Close() + c.Assert(err, jc.ErrorIsNil) + + ver, err := readBase() + c.Assert(err, jc.ErrorIsNil) + c.Assert(ver, gc.Equals, value.want) + } +} + +// RandomBytes returns n random bytes. +func RandomBytes(n int) ([]byte, error) { + buf := make([]byte, n) + _, err := io.ReadFull(rand.Reader, buf) + if err != nil { + return nil, fmt.Errorf("cannot read random bytes: %v", err) + } + return buf, nil +} + +// RandomPassword generates a random base64-encoded password. +func RandomPassword() (string, error) { + b, err := RandomBytes(randomPasswordBytes) + if err != nil { + return "", err + } + return base64.StdEncoding.EncodeToString(b), nil +} diff --git a/core/os/os.go b/core/os/os.go index 54cebc76fddc..314805d8da22 100644 --- a/core/os/os.go +++ b/core/os/os.go @@ -9,69 +9,6 @@ import ( var HostOS = hostOS // for monkey patching -type OSType int - -const ( - Unknown OSType = iota - Ubuntu - Windows - OSX - CentOS - GenericLinux -) - -func (t OSType) String() string { - switch t { - case Ubuntu: - return "Ubuntu" - case Windows: - return "Windows" - case OSX: - return "OSX" - case CentOS: - return "CentOS" - case GenericLinux: - return "GenericLinux" - } - return "Unknown" -} - -var validOSTypeNames map[string]OSType - -func init() { - osTypes := []OSType{ - Unknown, - Ubuntu, - Windows, - CentOS, - GenericLinux, - } - validOSTypeNames = make(map[string]OSType) - for _, osType := range osTypes { - validOSTypeNames[strings.ToLower(osType.String())] = osType - } -} - -// IsValidOSTypeName returns true if osType is a -// valid os type name. -func IsValidOSTypeName(osType string) bool { - for n := range validOSTypeNames { - if n == osType { - return true - } - } - return false -} - -// OSTypeForName return the named OS. -func OSTypeForName(name string) OSType { - os, ok := validOSTypeNames[name] - if ok { - return os - } - return Unknown -} - // HostOSTypeName returns the name of the host OS. func HostOSTypeName() (osTypeName string) { defer func() { @@ -81,21 +18,3 @@ func HostOSTypeName() (osTypeName string) { }() return strings.ToLower(HostOS().String()) } - -// EquivalentTo returns true if the OS type is equivalent to another -// OS type. -func (t OSType) EquivalentTo(t2 OSType) bool { - if t == t2 { - return true - } - return t.IsLinux() && t2.IsLinux() -} - -// IsLinux returns true if the OS type is a Linux variant. -func (t OSType) IsLinux() bool { - switch t { - case Ubuntu, CentOS, GenericLinux: - return true - } - return false -} diff --git a/core/os/os_darwin.go b/core/os/os_darwin.go index 196d5537889a..e0fa7612ed54 100644 --- a/core/os/os_darwin.go +++ b/core/os/os_darwin.go @@ -3,6 +3,8 @@ package os -func hostOS() OSType { - return OSX +import "github.com/juju/juju/core/os/ostype" + +func hostOS() ostype.OSType { + return ostype.OSX } diff --git a/core/os/os_linux.go b/core/os/os_linux.go index b50349928a02..5240c282e7ac 100644 --- a/core/os/os_linux.go +++ b/core/os/os_linux.go @@ -8,6 +8,8 @@ import ( stdos "os" "strings" "sync" + + "github.com/juju/juju/core/os/ostype" ) var ( @@ -15,10 +17,10 @@ var ( // the linux type release version. osReleaseFile = "/etc/os-release" osOnce sync.Once - os OSType // filled in by the first call to hostOS + os ostype.OSType // filled in by the first call to hostOS ) -func hostOS() OSType { +func hostOS() ostype.OSType { osOnce.Do(func() { var err error os, err = updateOS(osReleaseFile) @@ -29,18 +31,18 @@ func hostOS() OSType { return os } -func updateOS(f string) (OSType, error) { +func updateOS(f string) (ostype.OSType, error) { values, err := ReadOSRelease(f) if err != nil { - return Unknown, err + return ostype.Unknown, err } switch values["ID"] { - case strings.ToLower(Ubuntu.String()): - return Ubuntu, nil - case strings.ToLower(CentOS.String()): - return CentOS, nil + case strings.ToLower(ostype.Ubuntu.String()): + return ostype.Ubuntu, nil + case strings.ToLower(ostype.CentOS.String()): + return ostype.CentOS, nil default: - return GenericLinux, nil + return ostype.GenericLinux, nil } } @@ -64,5 +66,8 @@ func ReadOSRelease(f string) (map[string]string, error) { if _, ok := values["ID"]; !ok { return nil, errors.New("OS release file is missing ID") } + if _, ok := values["VERSION_ID"]; !ok { + return nil, errors.New("OS release file is missing VERSION_ID") + } return values, nil } diff --git a/core/os/os_test.go b/core/os/os_test.go index 815bf35bacb9..82266c80f02a 100644 --- a/core/os/os_test.go +++ b/core/os/os_test.go @@ -6,8 +6,9 @@ package os import ( "runtime" - jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" + + "github.com/juju/juju/core/os/ostype" ) type osSuite struct { @@ -19,14 +20,14 @@ func (s *osSuite) TestHostOS(c *gc.C) { os := HostOS() switch runtime.GOOS { case "windows": - c.Assert(os, gc.Equals, Windows) - case "OSX": - c.Assert(os, gc.Equals, OSX) + c.Assert(os, gc.Equals, ostype.Windows) + case "darwin": + c.Assert(os, gc.Equals, ostype.OSX) case "linux": // TODO(mjs) - this should really do more by patching out // osReleaseFile and testing the corner cases. switch os { - case Ubuntu, CentOS, GenericLinux: + case ostype.Ubuntu, ostype.CentOS, ostype.GenericLinux: default: c.Fatalf("unknown linux version: %v", os) } @@ -34,23 +35,3 @@ func (s *osSuite) TestHostOS(c *gc.C) { c.Fatalf("unsupported operating system: %v", runtime.GOOS) } } - -func (s *osSuite) TestEquivalentTo(c *gc.C) { - c.Check(Ubuntu.EquivalentTo(CentOS), jc.IsTrue) - c.Check(Ubuntu.EquivalentTo(GenericLinux), jc.IsTrue) - c.Check(GenericLinux.EquivalentTo(Ubuntu), jc.IsTrue) - c.Check(CentOS.EquivalentTo(CentOS), jc.IsTrue) -} - -func (s *osSuite) TestIsLinux(c *gc.C) { - c.Check(Ubuntu.IsLinux(), jc.IsTrue) - c.Check(CentOS.IsLinux(), jc.IsTrue) - c.Check(GenericLinux.IsLinux(), jc.IsTrue) - - c.Check(Windows.IsLinux(), jc.IsFalse) - c.Check(Unknown.IsLinux(), jc.IsFalse) - - c.Check(OSX.EquivalentTo(Ubuntu), jc.IsFalse) - c.Check(OSX.EquivalentTo(Windows), jc.IsFalse) - c.Check(GenericLinux.EquivalentTo(OSX), jc.IsFalse) -} diff --git a/core/os/os_unknown.go b/core/os/os_unknown.go index 9d35c03eff7b..89c0c698ee00 100644 --- a/core/os/os_unknown.go +++ b/core/os/os_unknown.go @@ -5,6 +5,8 @@ package os -func hostOS() OSType { - return Unknown +import "github.com/juju/juju/core/os/ostype" + +func hostOS() ostype.OSType { + return ostype.Unknown } diff --git a/core/os/os_windows.go b/core/os/os_windows.go index 78828fa04360..f482e97ac93f 100644 --- a/core/os/os_windows.go +++ b/core/os/os_windows.go @@ -3,6 +3,8 @@ package os -func hostOS() OSType { - return Windows +import "github.com/juju/juju/core/os/ostype" + +func hostOS() ostype.OSType { + return ostype.Windows } diff --git a/core/os/ostype/ostype.go b/core/os/ostype/ostype.go new file mode 100644 index 000000000000..010df9f78c31 --- /dev/null +++ b/core/os/ostype/ostype.go @@ -0,0 +1,91 @@ +// Copyright 2024 Canonical Ltd. +// Licensed under the LGPLv3, see LICENCE file for details. + +package ostype + +import "strings" + +type OSType int + +const ( + Unknown OSType = iota + Ubuntu + Windows + OSX + CentOS + GenericLinux + Kubernetes +) + +func (t OSType) String() string { + switch t { + case Ubuntu: + return "Ubuntu" + case Windows: + return "Windows" + case OSX: + return "OSX" + case CentOS: + return "CentOS" + case GenericLinux: + return "GenericLinux" + case Kubernetes: + return "Kubernetes" + } + return "Unknown" +} + +// EquivalentTo returns true if the OS type is equivalent to another +// OS type. +func (t OSType) EquivalentTo(t2 OSType) bool { + if t == t2 { + return true + } + return t.IsLinux() && t2.IsLinux() +} + +// IsLinux returns true if the OS type is a Linux variant. +func (t OSType) IsLinux() bool { + switch t { + case Ubuntu, CentOS, GenericLinux: + return true + } + return false +} + +var validOSTypeNames map[string]OSType + +func init() { + osTypes := []OSType{ + Unknown, + Ubuntu, + Windows, + CentOS, + GenericLinux, + Kubernetes, + } + validOSTypeNames = make(map[string]OSType) + for _, osType := range osTypes { + validOSTypeNames[strings.ToLower(osType.String())] = osType + } +} + +// IsValidOSTypeName returns true if osType is a +// valid os type name. +func IsValidOSTypeName(osType string) bool { + for n := range validOSTypeNames { + if n == osType { + return true + } + } + return false +} + +// OSTypeForName return the named OS. +func OSTypeForName(name string) OSType { + os, ok := validOSTypeNames[name] + if ok { + return os + } + return Unknown +} diff --git a/core/os/ostype/ostype_test.go b/core/os/ostype/ostype_test.go new file mode 100644 index 000000000000..6fc8428833b4 --- /dev/null +++ b/core/os/ostype/ostype_test.go @@ -0,0 +1,33 @@ +// Copyright 2024 Canonical Ltd. +// Licensed under the LGPLv3, see LICENCE file for details. + +package ostype + +import ( + jc "github.com/juju/testing/checkers" + gc "gopkg.in/check.v1" +) + +type osTypeSuite struct{} + +var _ = gc.Suite(&osTypeSuite{}) + +func (s *osTypeSuite) TestEquivalentTo(c *gc.C) { + c.Check(Ubuntu.EquivalentTo(CentOS), jc.IsTrue) + c.Check(Ubuntu.EquivalentTo(GenericLinux), jc.IsTrue) + c.Check(GenericLinux.EquivalentTo(Ubuntu), jc.IsTrue) + c.Check(CentOS.EquivalentTo(CentOS), jc.IsTrue) +} + +func (s *osTypeSuite) TestIsLinux(c *gc.C) { + c.Check(Ubuntu.IsLinux(), jc.IsTrue) + c.Check(CentOS.IsLinux(), jc.IsTrue) + c.Check(GenericLinux.IsLinux(), jc.IsTrue) + + c.Check(Windows.IsLinux(), jc.IsFalse) + c.Check(Unknown.IsLinux(), jc.IsFalse) + + c.Check(OSX.EquivalentTo(Ubuntu), jc.IsFalse) + c.Check(OSX.EquivalentTo(Windows), jc.IsFalse) + c.Check(GenericLinux.EquivalentTo(OSX), jc.IsFalse) +} diff --git a/core/os/ostype/package_test.go b/core/os/ostype/package_test.go new file mode 100644 index 000000000000..c1041da9b683 --- /dev/null +++ b/core/os/ostype/package_test.go @@ -0,0 +1,14 @@ +// Copyright 2024 Canonical Ltd. +// Licensed under the LGPLv3, see LICENCE file for details. + +package ostype + +import ( + "testing" + + gc "gopkg.in/check.v1" +) + +func Test(t *testing.T) { + gc.TestingT(t) +} diff --git a/core/paths/logfile.go b/core/paths/logfile.go index dd889aa14107..b049179832b5 100644 --- a/core/paths/logfile.go +++ b/core/paths/logfile.go @@ -12,6 +12,7 @@ import ( "github.com/juju/errors" jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" ) // LogfilePermission is the file mode to use for log files. @@ -62,7 +63,7 @@ func PrimeLogFile(path string) error { // SyslogUserGroup returns the names of the user and group that own the log files. func SyslogUserGroup() (string, string) { switch jujuos.HostOS() { - case jujuos.CentOS: + case ostype.CentOS: return "root", "adm" default: return "syslog", "adm" diff --git a/core/paths/paths.go b/core/paths/paths.go index 1da15c4c3839..80e849868e75 100644 --- a/core/paths/paths.go +++ b/core/paths/paths.go @@ -8,7 +8,7 @@ import ( "os" "runtime" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" ) type OS int // strongly typed runtime.GOOS value to help with refactoring @@ -99,8 +99,8 @@ func CurrentOS() OS { // OSType converts the given os name to an OS value. func OSType(osName string) OS { - switch jujuos.OSTypeForName(osName) { - case jujuos.Windows: + switch ostype.OSTypeForName(osName) { + case ostype.Windows: return OSWindows default: return OSUnixLike diff --git a/environs/bootstrap/bootstrap.go b/environs/bootstrap/bootstrap.go index 9ac26bd9eb3c..823cae34fe82 100644 --- a/environs/bootstrap/bootstrap.go +++ b/environs/bootstrap/bootstrap.go @@ -352,7 +352,7 @@ func bootstrapIAAS( // characteristics of the instance we are about to bootstrap, use this // information to backfill in any missing series and/or arch contstraints. if detector, supported := environ.(environs.HardwareCharacteristicsDetector); supported { - detectedSeries, err := detector.DetectSeries() + detectedBase, err := detector.DetectBase() if err != nil { return errors.Trace(err) } @@ -361,12 +361,8 @@ func bootstrapIAAS( return errors.Trace(err) } - if args.BootstrapBase.Empty() && detectedSeries != "" { - base, err := corebase.GetBaseFromSeries(detectedSeries) - if err != nil { - base = jujuversion.DefaultSupportedLTSBase() - } - args.BootstrapBase = base + if args.BootstrapBase.Empty() && !detectedBase.Empty() { + args.BootstrapBase = detectedBase logger.Debugf("auto-selecting bootstrap series %q", args.BootstrapBase.String()) } if args.BootstrapConstraints.Arch == nil && diff --git a/environs/bootstrap/bootstrap_test.go b/environs/bootstrap/bootstrap_test.go index d4b9df6ce72d..c1070e9994d4 100644 --- a/environs/bootstrap/bootstrap_test.go +++ b/environs/bootstrap/bootstrap_test.go @@ -28,6 +28,7 @@ import ( "github.com/juju/juju/core/constraints" "github.com/juju/juju/core/instance" jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs" "github.com/juju/juju/environs/bootstrap" environscmd "github.com/juju/juju/environs/cmd" @@ -603,7 +604,7 @@ func (s *bootstrapSuite) TestBootstrapLocalTools(c *gc.C) { // Client host is CentOS system, wanting to bootstrap a trusty // controller. This is fine. - s.PatchValue(&jujuos.HostOS, func() jujuos.OSType { return jujuos.CentOS }) + s.PatchValue(&jujuos.HostOS, func() ostype.OSType { return ostype.CentOS }) s.PatchValue(&arch.HostArch, func() string { return arch.AMD64 }) s.PatchValue(bootstrap.FindTools, func(context.Context, envtools.SimplestreamsFetcher, environs.BootstrapEnviron, int, int, []string, tools.Filter) (tools.List, error) { return nil, errors.NotFoundf("tools") @@ -631,7 +632,7 @@ func (s *bootstrapSuite) TestBootstrapLocalToolsMismatchingOS(c *gc.C) { // Client host is a Windows system, wanting to bootstrap a jammy // controller with local tools. This can't work. - s.PatchValue(&jujuos.HostOS, func() jujuos.OSType { return jujuos.Windows }) + s.PatchValue(&jujuos.HostOS, func() ostype.OSType { return ostype.Windows }) s.PatchValue(&arch.HostArch, func() string { return arch.AMD64 }) s.PatchValue(bootstrap.FindTools, func(context.Context, envtools.SimplestreamsFetcher, environs.BootstrapEnviron, int, int, []string, tools.Filter) (tools.List, error) { return nil, errors.NotFoundf("tools") @@ -656,7 +657,7 @@ func (s *bootstrapSuite) TestBootstrapLocalToolsDifferentLinuxes(c *gc.C) { // bootstrap a trusty controller with local tools. This should be // OK. - s.PatchValue(&jujuos.HostOS, func() jujuos.OSType { return jujuos.GenericLinux }) + s.PatchValue(&jujuos.HostOS, func() ostype.OSType { return ostype.GenericLinux }) s.PatchValue(&arch.HostArch, func() string { return arch.AMD64 }) s.PatchValue(bootstrap.FindTools, func(context.Context, envtools.SimplestreamsFetcher, environs.BootstrapEnviron, int, int, []string, tools.Filter) (tools.List, error) { return nil, errors.NotFoundf("tools") @@ -683,7 +684,6 @@ func (s *bootstrapSuite) TestBootstrapLocalToolsDifferentLinuxes(c *gc.C) { func (s *bootstrapSuite) TestBootstrapBuildAgent(c *gc.C) { // Patch out HostArch and FindTools to allow the test to pass on other architectures, // such as s390. - s.PatchValue(&jujuos.HostOS, func() jujuos.OSType { return jujuos.Ubuntu }) s.PatchValue(&arch.HostArch, func() string { return arch.ARM64 }) s.PatchValue(bootstrap.FindTools, func(context.Context, envtools.SimplestreamsFetcher, environs.BootstrapEnviron, int, int, []string, tools.Filter) (tools.List, error) { c.Fatal("should not call FindTools if BuildAgent is specified") @@ -773,7 +773,6 @@ func (s *bootstrapSuite) TestBootstrapNoToolsNonReleaseStream(c *gc.C) { // Patch out HostArch and FindTools to allow the test to pass on other architectures, // such as s390. s.PatchValue(&arch.HostArch, func() string { return arch.ARM64 }) - s.PatchValue(&jujuos.HostOS, func() jujuos.OSType { return jujuos.Ubuntu }) s.PatchValue(bootstrap.FindTools, func(context.Context, envtools.SimplestreamsFetcher, environs.BootstrapEnviron, int, int, []string, tools.Filter) (tools.List, error) { return nil, errors.NotFoundf("tools") }) @@ -795,7 +794,6 @@ func (s *bootstrapSuite) TestBootstrapNoToolsNonReleaseStream(c *gc.C) { } func (s *bootstrapSuite) TestBootstrapNoToolsDevelopmentConfig(c *gc.C) { - s.PatchValue(&jujuos.HostOS, func() jujuos.OSType { return jujuos.Ubuntu }) s.PatchValue(&arch.HostArch, func() string { return arch.ARM64 }) s.PatchValue(bootstrap.FindTools, func(context.Context, envtools.SimplestreamsFetcher, environs.BootstrapEnviron, int, int, []string, tools.Filter) (tools.List, error) { return nil, errors.NotFoundf("tools") @@ -1299,7 +1297,6 @@ func (s *bootstrapSuite) TestBootstrapSpecificVersionClientMajorMismatch(c *gc.C } func (s *bootstrapSuite) TestAvailableToolsInvalidArch(c *gc.C) { - s.PatchValue(&jujuos.HostOS, func() jujuos.OSType { return jujuos.Ubuntu }) s.PatchValue(&arch.HostArch, func() string { return arch.S390X }) @@ -1330,7 +1327,7 @@ func (s *bootstrapSuite) TestAvailableToolsInvalidArch(c *gc.C) { } func (s *bootstrapSuite) TestTargetSeriesOverride(c *gc.C) { - env := newBootstrapEnvironWithHardwareDetection("foo", "artful", "amd64", useDefaultKeys, nil) + env := newBootstrapEnvironWithHardwareDetection("foo", corebase.MustParseBaseFromString("ubuntu@17.10"), "amd64", useDefaultKeys, nil) err := bootstrap.Bootstrap(envtesting.BootstrapTestContext(c), env, s.callContext, bootstrap.BootstrapParams{ AdminSecret: "fake-moon-landing", @@ -1343,7 +1340,7 @@ func (s *bootstrapSuite) TestTargetSeriesOverride(c *gc.C) { } func (s *bootstrapSuite) TestTargetArchOverride(c *gc.C) { - env := newBootstrapEnvironWithHardwareDetection("foo", "bionic", "riscv", useDefaultKeys, nil) + env := newBootstrapEnvironWithHardwareDetection("foo", corebase.MustParseBaseFromString("ubuntu@18.04"), "riscv", useDefaultKeys, nil) err := bootstrap.Bootstrap(envtesting.BootstrapTestContext(c), env, s.callContext, bootstrap.BootstrapParams{ AdminSecret: "fake-moon-landing", @@ -1374,7 +1371,7 @@ func (s *bootstrapSuite) TestTargetSeriesAndArchOverridePriority(c *gc.C) { c.Assert(err, jc.ErrorIsNil) envtesting.UploadFakeTools(c, stor, "released", "released") - env := newBootstrapEnvironWithHardwareDetection("foo", "haiku", "riscv", useDefaultKeys, nil) + env := newBootstrapEnvironWithHardwareDetection("foo", corebase.MustParseBaseFromString("ubuntu@17.04"), "riscv", useDefaultKeys, nil) err = bootstrap.Bootstrap(envtesting.BootstrapTestContext(c), env, s.callContext, bootstrap.BootstrapParams{ AdminSecret: "fake-moon-landing", @@ -1527,11 +1524,11 @@ func (e bootstrapEnvironNoExplicitArchitectures) ConstraintsValidator(envcontext type bootstrapEnvironWithHardwareDetection struct { *bootstrapEnviron - detectedSeries string - detectedHW *instance.HardwareCharacteristics + detectedBase corebase.Base + detectedHW *instance.HardwareCharacteristics } -func newBootstrapEnvironWithHardwareDetection(name, detectedSeries, detectedArch string, defaultKeys bool, extraAttrs map[string]interface{}) *bootstrapEnvironWithHardwareDetection { +func newBootstrapEnvironWithHardwareDetection(name string, detectedBase corebase.Base, detectedArch string, defaultKeys bool, extraAttrs map[string]interface{}) *bootstrapEnvironWithHardwareDetection { var hw = new(instance.HardwareCharacteristics) if detectedArch != "" { hw.Arch = &detectedArch @@ -1539,13 +1536,13 @@ func newBootstrapEnvironWithHardwareDetection(name, detectedSeries, detectedArch return &bootstrapEnvironWithHardwareDetection{ bootstrapEnviron: newEnviron(name, defaultKeys, extraAttrs), - detectedSeries: detectedSeries, + detectedBase: detectedBase, detectedHW: hw, } } -func (e bootstrapEnvironWithHardwareDetection) DetectSeries() (string, error) { - return e.detectedSeries, nil +func (e bootstrapEnvironWithHardwareDetection) DetectBase() (corebase.Base, error) { + return e.detectedBase, nil } func (e bootstrapEnvironWithHardwareDetection) DetectHardware() (*instance.HardwareCharacteristics, error) { return e.detectedHW, nil diff --git a/environs/bootstrap/tools.go b/environs/bootstrap/tools.go index 21a23f59963e..9bc052c65bc2 100644 --- a/environs/bootstrap/tools.go +++ b/environs/bootstrap/tools.go @@ -15,6 +15,7 @@ import ( corebase "github.com/juju/juju/core/base" "github.com/juju/juju/core/constraints" coreos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs" envtools "github.com/juju/juju/environs/tools" coretools "github.com/juju/juju/internal/tools" @@ -45,7 +46,7 @@ func validateUploadAllowed(env environs.ConfigGetter, toolsArch *string, toolsBa } hostOS := coreos.HostOS() if toolsBase != nil { - if !coreos.OSTypeForName(toolsBase.OS).EquivalentTo(hostOS) { + if !ostype.OSTypeForName(toolsBase.OS).EquivalentTo(hostOS) { return errors.Errorf("cannot use agent built for %q using a machine running %q", toolsBase.String(), hostOS) } } @@ -92,7 +93,7 @@ func locallyBuildableTools() (buildable coretools.List, _ version.Number, _ erro buildNumber := jujuversion.Current // Increment the build number so we know it's a custom build. buildNumber.Build++ - if !coreos.HostOS().EquivalentTo(coreos.Ubuntu) { + if !coreos.HostOS().EquivalentTo(ostype.Ubuntu) { return buildable, buildNumber, nil } binary := version.Binary{ diff --git a/environs/bootstrap/tools_test.go b/environs/bootstrap/tools_test.go index 1f2598b0d3dd..f3586ab4f7df 100644 --- a/environs/bootstrap/tools_test.go +++ b/environs/bootstrap/tools_test.go @@ -14,6 +14,7 @@ import ( "github.com/juju/juju/core/arch" corebase "github.com/juju/juju/core/base" "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs" "github.com/juju/juju/environs/bootstrap" "github.com/juju/juju/environs/envcontext" @@ -70,7 +71,7 @@ func (s *toolsSuite) TestValidateUploadAllowed(c *gc.C) { arm64 := "arm64" ubuntuFocal := corebase.MustParseBaseFromString("ubuntu@20.04") s.PatchValue(&arch.HostArch, func() string { return arm64 }) - s.PatchValue(&os.HostOS, func() os.OSType { return os.Ubuntu }) + s.PatchValue(&os.HostOS, func() ostype.OSType { return ostype.Ubuntu }) validator, err := env.ConstraintsValidator(envcontext.WithoutCredentialInvalidator(context.Background())) c.Assert(err, jc.ErrorIsNil) err = bootstrap.ValidateUploadAllowed(env, &arm64, &ubuntuFocal, validator) diff --git a/environs/interface.go b/environs/interface.go index 44d8d78309bc..247f8a47622a 100644 --- a/environs/interface.go +++ b/environs/interface.go @@ -621,13 +621,13 @@ type DefaultConstraintsChecker interface { // provide advance information about the series and hardware for controller // instances that have not been provisioned yet. type HardwareCharacteristicsDetector interface { - // DetectSeries returns the series for the controller instance. - DetectSeries() (string, error) + // DetectBase returns the base for the controller instance. + DetectBase() (corebase.Base, error) // DetectHardware returns the hardware characteristics for the // controller instance. DetectHardware() (*instance.HardwareCharacteristics, error) // UpdateModelConstraints returns true if the model constraints should - // be updated based on the returns of DetectSeries() and + // be updated based on the returns of DetectBase() and // DetectHardware(). UpdateModelConstraints() bool } diff --git a/environs/manual/sshprovisioner/fakessh_test.go b/environs/manual/sshprovisioner/fakessh_test.go index 42b77647c3f6..024cad0c7367 100644 --- a/environs/manual/sshprovisioner/fakessh_test.go +++ b/environs/manual/sshprovisioner/fakessh_test.go @@ -14,6 +14,7 @@ import ( jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" + corebase "github.com/juju/juju/core/base" "github.com/juju/juju/environs/manual/sshprovisioner" "github.com/juju/juju/internal/service" ) @@ -86,17 +87,15 @@ func installFakeSSH(c *gc.C, input, output interface{}, rc int) testing.Restorer } // installDetectionFakeSSH installs a fake SSH command, which will respond -// to the series/hardware detection script with the specified -// series/arch. -func installDetectionFakeSSH(c *gc.C, series, arch string) testing.Restorer { - if series == "" { - series = "precise" - } +// to the base/hardware detection script with the specified +// base/arch. +func installDetectionFakeSSH(c *gc.C, base corebase.Base, arch string) testing.Restorer { if arch == "" { arch = "amd64" } detectionoutput := strings.Join([]string{ - series, + base.OS, + base.Channel.String(), arch, "MemTotal: 4096 kB", "processor: 0", @@ -106,8 +105,8 @@ func installDetectionFakeSSH(c *gc.C, series, arch string) testing.Restorer { // fakeSSH wraps the invocation of InstallFakeSSH based on the parameters. type fakeSSH struct { - Series string - Arch string + Base corebase.Base + Arch string // Provisioned should be set to true if the fakeSSH script // should respond to checkProvisioned with a non-empty result. @@ -146,7 +145,7 @@ func (r fakeSSH) install(c *gc.C) testing.Restorer { add(nil, nil, r.ProvisionAgentExitCode) } if !r.SkipDetection { - restore.Add(installDetectionFakeSSH(c, r.Series, r.Arch)) + restore.Add(installDetectionFakeSSH(c, r.Base, r.Arch)) } var checkProvisionedOutput interface{} if r.Provisioned { diff --git a/environs/manual/sshprovisioner/init_test.go b/environs/manual/sshprovisioner/init_test.go index a3d925d54fc7..578ca14e3b6e 100644 --- a/environs/manual/sshprovisioner/init_test.go +++ b/environs/manual/sshprovisioner/init_test.go @@ -10,6 +10,7 @@ import ( jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" + corebase "github.com/juju/juju/core/base" "github.com/juju/juju/environs/manual/sshprovisioner" "github.com/juju/juju/internal/service" "github.com/juju/juju/testing" @@ -21,22 +22,24 @@ type initialisationSuite struct { var _ = gc.Suite(&initialisationSuite{}) -func (s *initialisationSuite) TestDetectSeries(c *gc.C) { +func (s *initialisationSuite) TestDetectBase(c *gc.C) { response := strings.Join([]string{ - "edgy", + "ubuntu", + "6.10", "armv4", "MemTotal: 4096 kB", "processor: 0", }, "\n") defer installFakeSSH(c, sshprovisioner.DetectionScript, response, 0)() - _, series, err := sshprovisioner.DetectSeriesAndHardwareCharacteristics("whatever") + _, base, err := sshprovisioner.DetectBaseAndHardwareCharacteristics("whatever") c.Assert(err, jc.ErrorIsNil) - c.Assert(series, gc.Equals, "edgy") + c.Assert(base, gc.Equals, corebase.MustParseBaseFromString("ubuntu@6.10")) } func (s *initialisationSuite) TestDetectionError(c *gc.C) { scriptResponse := strings.Join([]string{ - "edgy", + "ubuntu", + "6.10", "ppc64le", "MemTotal: 4096 kB", "processor: 0", @@ -44,11 +47,11 @@ func (s *initialisationSuite) TestDetectionError(c *gc.C) { // if the script fails for whatever reason, then checkProvisioned // will return an error. stderr will be included in the error message. defer installFakeSSH(c, sshprovisioner.DetectionScript, []string{scriptResponse, "oh noes"}, 33)() - _, _, err := sshprovisioner.DetectSeriesAndHardwareCharacteristics("hostname") + _, _, err := sshprovisioner.DetectBaseAndHardwareCharacteristics("hostname") c.Assert(err, gc.ErrorMatches, "subprocess encountered error code 33 \\(oh noes\\)") // if the script doesn't fail, stderr is simply ignored. defer installFakeSSH(c, sshprovisioner.DetectionScript, []string{scriptResponse, "non-empty-stderr"}, 0)() - hc, _, err := sshprovisioner.DetectSeriesAndHardwareCharacteristics("hostname") + hc, _, err := sshprovisioner.DetectBaseAndHardwareCharacteristics("hostname") c.Assert(err, jc.ErrorIsNil) c.Assert(hc.String(), gc.Equals, "arch=ppc64el cores=1 mem=4M") } @@ -60,12 +63,12 @@ func (s *initialisationSuite) TestDetectHardwareCharacteristics(c *gc.C) { expectedHc string }{{ "Single CPU socket, single core, no hyper-threading", - []string{"edgy", "s390x", "MemTotal: 4096 kB", "processor: 0"}, + []string{"ubuntu", "6.10", "s390x", "MemTotal: 4096 kB", "processor: 0"}, "arch=s390x cores=1 mem=4M", }, { "Single CPU socket, single core, hyper-threading", []string{ - "edgy", "s390x", "MemTotal: 4096 kB", + "ubuntu", "6.10", "s390x", "MemTotal: 4096 kB", "processor: 0", "physical id: 0", "cpu cores: 1", @@ -77,7 +80,7 @@ func (s *initialisationSuite) TestDetectHardwareCharacteristics(c *gc.C) { }, { "Single CPU socket, dual-core, no hyper-threading", []string{ - "edgy", "s390x", "MemTotal: 4096 kB", + "ubuntu", "6.10", "s390x", "MemTotal: 4096 kB", "processor: 0", "physical id: 0", "cpu cores: 2", @@ -89,7 +92,7 @@ func (s *initialisationSuite) TestDetectHardwareCharacteristics(c *gc.C) { }, { "Dual CPU socket, each single-core, hyper-threading", []string{ - "edgy", "s390x", "MemTotal: 4096 kB", + "ubuntu", "6.10", "s390x", "MemTotal: 4096 kB", "processor: 0", "physical id: 0", "cpu cores: 1", @@ -107,7 +110,7 @@ func (s *initialisationSuite) TestDetectHardwareCharacteristics(c *gc.C) { }, { "4 CPU sockets, each single-core, no hyper-threading, no physical id field", []string{ - "edgy", "arm64", "MemTotal: 16384 kB", + "ubuntu", "6.10", "arm64", "MemTotal: 16384 kB", "processor: 0", "processor: 1", "processor: 2", @@ -120,7 +123,7 @@ func (s *initialisationSuite) TestDetectHardwareCharacteristics(c *gc.C) { c.Logf("test %d: %s", i, test.summary) scriptResponse := strings.Join(test.scriptResponse, "\n") defer installFakeSSH(c, sshprovisioner.DetectionScript, scriptResponse, 0)() - hc, _, err := sshprovisioner.DetectSeriesAndHardwareCharacteristics("hostname") + hc, _, err := sshprovisioner.DetectBaseAndHardwareCharacteristics("hostname") c.Assert(err, jc.ErrorIsNil) c.Assert(hc.String(), gc.Equals, test.expectedHc) } diff --git a/environs/manual/sshprovisioner/provisioner_test.go b/environs/manual/sshprovisioner/provisioner_test.go index 34e2f67c57d7..1e48f5b8869f 100644 --- a/environs/manual/sshprovisioner/provisioner_test.go +++ b/environs/manual/sshprovisioner/provisioner_test.go @@ -21,7 +21,7 @@ import ( "github.com/juju/juju/agent" "github.com/juju/juju/api" "github.com/juju/juju/core/arch" - "github.com/juju/juju/core/base" + corebase "github.com/juju/juju/core/base" "github.com/juju/juju/core/model" "github.com/juju/juju/environs/manual" "github.com/juju/juju/environs/manual/sshprovisioner" @@ -89,8 +89,7 @@ func (s *provisionerSuite) getArgs(c *gc.C) manual.ProvisionMachineArgs { } func (s *provisionerSuite) TestProvisionMachine(c *gc.C) { - series, err := base.GetSeriesFromBase(jujuversion.DefaultSupportedLTSBase()) - c.Assert(err, jc.ErrorIsNil) + base := jujuversion.DefaultSupportedLTSBase() args := s.getArgs(c) hostname := args.Host @@ -98,7 +97,7 @@ func (s *provisionerSuite) TestProvisionMachine(c *gc.C) { args.User = "ubuntu" defer fakeSSH{ - Series: series, + Base: base, Arch: arch.AMD64, InitUbuntuUser: true, SkipProvisionAgent: true, @@ -107,7 +106,7 @@ func (s *provisionerSuite) TestProvisionMachine(c *gc.C) { for i, errorCode := range []int{255, 0} { c.Logf("test %d: code %d", i, errorCode) defer fakeSSH{ - Series: series, + Base: base, Arch: arch.AMD64, InitUbuntuUser: true, ProvisionAgentExitCode: errorCode, @@ -133,7 +132,7 @@ func (s *provisionerSuite) TestProvisionMachine(c *gc.C) { SkipDetection: true, SkipProvisionAgent: true, }.install(c).Restore() - _, err = sshprovisioner.ProvisionMachine(args) + _, err := sshprovisioner.ProvisionMachine(args) c.Assert(err, gc.Equals, manual.ErrProvisioned) defer fakeSSH{ Provisioned: true, @@ -147,11 +146,10 @@ func (s *provisionerSuite) TestProvisionMachine(c *gc.C) { } func (s *provisionerSuite) TestProvisioningScript(c *gc.C) { - series, err := base.GetSeriesFromBase(jujuversion.DefaultSupportedLTSBase()) - c.Assert(err, jc.ErrorIsNil) + base := jujuversion.DefaultSupportedLTSBase() defer fakeSSH{ - Series: series, + Base: base, Arch: arch.AMD64, InitUbuntuUser: true, }.install(c).Restore() @@ -161,7 +159,7 @@ func (s *provisionerSuite) TestProvisioningScript(c *gc.C) { ControllerTag: testing.ControllerTag, MachineId: "10", MachineNonce: "5432", - Base: base.MustParseBaseFromString("ubuntu@22.04"), + Base: corebase.MustParseBaseFromString("ubuntu@22.04"), APIInfo: &api.Info{ Addrs: []string{"127.0.0.1:1234"}, Password: "pw2", @@ -182,7 +180,7 @@ func (s *provisionerSuite) TestProvisioningScript(c *gc.C) { Version: version.MustParseBinary("6.6.6-ubuntu-amd64"), URL: "https://example.org", }} - err = icfg.SetTools(tools) + err := icfg.SetTools(tools) c.Assert(err, jc.ErrorIsNil) script, err := sshprovisioner.ProvisioningScript(icfg) diff --git a/environs/manual/sshprovisioner/sshprovisioner.go b/environs/manual/sshprovisioner/sshprovisioner.go index 4301e7a64b74..e6c4cc0dcaaf 100644 --- a/environs/manual/sshprovisioner/sshprovisioner.go +++ b/environs/manual/sshprovisioner/sshprovisioner.go @@ -100,13 +100,13 @@ if [ ! -z "$authorized_keys" ]; then su ubuntu -c 'printf "%%s\n" "$authorized_keys" >> ~/.ssh/authorized_keys' fi` -// DetectSeriesAndHardwareCharacteristics detects the OS -// series and hardware characteristics of the remote machine +// DetectBaseAndHardwareCharacteristics detects the OS +// base and hardware characteristics of the remote machine // by connecting to the machine and executing a bash script. -var DetectSeriesAndHardwareCharacteristics = detectSeriesAndHardwareCharacteristics +var DetectBaseAndHardwareCharacteristics = detectBaseAndHardwareCharacteristics -func detectSeriesAndHardwareCharacteristics(host string) (hc instance.HardwareCharacteristics, series string, err error) { - logger.Infof("Detecting series and characteristics on %s", host) +func detectBaseAndHardwareCharacteristics(host string) (hc instance.HardwareCharacteristics, base corebase.Base, err error) { + logger.Infof("Detecting base and characteristics on %s", host) cmd := ssh.Command("ubuntu@"+host, []string{"/bin/bash"}, nil) var stdout, stderr bytes.Buffer cmd.Stdout = &stdout @@ -116,21 +116,26 @@ func detectSeriesAndHardwareCharacteristics(host string) (hc instance.HardwareCh if stderr.Len() != 0 { err = fmt.Errorf("%v (%v)", err, strings.TrimSpace(stderr.String())) } - return hc, "", err + return hc, base, err } lines := strings.Split(stdout.String(), "\n") - series = strings.TrimSpace(lines[0]) + os := strings.TrimSpace(lines[0]) + channel := strings.TrimSpace(lines[1]) + base, err = corebase.ParseBase(os, channel) + if err != nil { + return hc, base, err + } - arch := arch.NormaliseArch(lines[1]) + arch := arch.NormaliseArch(lines[2]) hc.Arch = &arch // HardwareCharacteristics wants memory in megabytes, // meminfo reports it in kilobytes. - memkB := strings.Fields(lines[2])[1] // "MemTotal: NNN kB" + memkB := strings.Fields(lines[3])[1] // "MemTotal: NNN kB" hc.Mem = new(uint64) *hc.Mem, err = strconv.ParseUint(memkB, 10, 0) if err != nil { - return hc, "", errors.Annotatef(err, "parsing %q", lines[2]) + return hc, base, errors.Annotatef(err, "parsing %q", lines[3]) } *hc.Mem /= 1024 @@ -141,14 +146,14 @@ func detectSeriesAndHardwareCharacteristics(host string) (hc instance.HardwareCh var physicalId string var processorEntries uint64 hc.CpuCores = new(uint64) - for _, line := range lines[3:] { + for _, line := range lines[4:] { if strings.HasPrefix(line, "physical id") { physicalId = strings.TrimSpace(strings.SplitN(line, ":", 2)[1]) } else if strings.HasPrefix(line, "cpu cores") { var cores uint64 value := strings.TrimSpace(strings.SplitN(line, ":", 2)[1]) if cores, err = strconv.ParseUint(value, 10, 0); err != nil { - return hc, "", err + return hc, base, err } if !recorded[physicalId] { *hc.CpuCores += cores @@ -165,8 +170,8 @@ func detectSeriesAndHardwareCharacteristics(host string) (hc instance.HardwareCh } // TODO(axw) calculate CpuPower. What algorithm do we use? - logger.Infof("series: %s, characteristics: %s", series, hc) - return hc, series, nil + logger.Infof("base: %s, characteristics: %s", base, hc) + return hc, base, nil } // CheckProvisioned checks if any juju init service already @@ -196,16 +201,11 @@ func checkProvisioned(host string) (bool, error) { } // detectionScript is the script to run on the remote machine to -// detect the OS series and hardware characteristics. +// detect the OS base and hardware characteristics. const detectionScript = `#!/bin/bash set -e -os_id=$(grep '^ID=' /etc/os-release | tr -d '"' | cut -d= -f2) -if [ "$os_id" = 'centos' ]; then - os_version=$(grep '^VERSION_ID=' /etc/os-release | tr -d '"' | cut -d= -f2) - echo "centos$os_version" -else - lsb_release -cs -fi +echo "$(grep '^ID=' /etc/os-release | tr -d '"' | cut -d= -f2)" +echo "$(grep '^VERSION_ID=' /etc/os-release | tr -d '"' | cut -d= -f2)" uname -m grep MemTotal /proc/meminfo cat /proc/cpuinfo` @@ -236,17 +236,13 @@ func gatherMachineParams(hostname string) (*params.AddMachineParams, error) { return nil, manual.ErrProvisioned } - hc, machineSeries, err := DetectSeriesAndHardwareCharacteristics(hostname) + hc, machineBase, err := DetectBaseAndHardwareCharacteristics(hostname) if err != nil { return nil, errors.Annotatef(err, "error detecting linux hardware characteristics") } - info, err := corebase.GetBaseFromSeries(machineSeries) - if err != nil { - return nil, errors.NotValidf("machine series %q", machineSeries) - } base := ¶ms.Base{ - Name: info.OS, - Channel: info.Channel.String(), + Name: machineBase.OS, + Channel: machineBase.Channel.String(), } // There will never be a corresponding "instance" that any provider diff --git a/environs/sync/sync_test.go b/environs/sync/sync_test.go index 639fd18a662d..23fc668ab384 100644 --- a/environs/sync/sync_test.go +++ b/environs/sync/sync_test.go @@ -27,6 +27,7 @@ import ( "github.com/juju/juju/core/arch" corebase "github.com/juju/juju/core/base" coreos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs/filestorage" "github.com/juju/juju/environs/simplestreams" "github.com/juju/juju/environs/storage" @@ -547,7 +548,7 @@ func (s *uploadSuite) TestMockBuildTools(c *gc.C) { current := version.MustParseBinary("1.9.1-ubuntu-amd64") s.PatchValue(&jujuversion.Current, current.Number) s.PatchValue(&arch.HostArch, func() string { return current.Arch }) - s.PatchValue(&coreos.HostOS, func() coreos.OSType { return coreos.Ubuntu }) + s.PatchValue(&coreos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) buildToolsFunc := toolstesting.GetMockBuildTools(c) builtTools, err := buildToolsFunc(true, "released", func(version.Number) version.Number { return jujuversion.Current }, diff --git a/environs/testing/tools.go b/environs/testing/tools.go index 046481c3f34d..b73caa714356 100644 --- a/environs/testing/tools.go +++ b/environs/testing/tools.go @@ -264,7 +264,7 @@ func RemoveFakeTools(c *gc.C, stor storage.Storage, toolsDir string) { err := stor.Remove(name) c.Check(err, jc.ErrorIsNil) defaultBase := jujuversion.DefaultSupportedLTSBase() - if coretesting.HostBase(c) != defaultBase { + if !defaultBase.IsCompatible(coretesting.HostBase(c)) { toolsVersion.Release = "ubuntu" name := envtools.StorageName(toolsVersion, toolsDir) err := stor.Remove(name) diff --git a/environs/tools/simplestreams.go b/environs/tools/simplestreams.go index 535debbdea14..38ecdb248cfa 100644 --- a/environs/tools/simplestreams.go +++ b/environs/tools/simplestreams.go @@ -19,7 +19,7 @@ import ( "github.com/juju/errors" "github.com/juju/version/v2" - coreos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs/simplestreams" "github.com/juju/juju/environs/storage" coretools "github.com/juju/juju/internal/tools" @@ -101,7 +101,7 @@ func (tc *ToolsConstraint) IndexIds() []string { func (tc *ToolsConstraint) ProductIds() ([]string, error) { var allIds []string for _, release := range tc.Releases { - if !coreos.IsValidOSTypeName(release) { + if !ostype.IsValidOSTypeName(release) { logger.Debugf("ignoring unknown os type %q", release) continue } @@ -150,7 +150,7 @@ func (t *ToolsMetadata) binary() (version.Binary, error) { } func (t *ToolsMetadata) productId() (string, error) { - if !coreos.IsValidOSTypeName(t.Release) { + if !ostype.IsValidOSTypeName(t.Release) { return "", errors.NotValidf("os type %q", t.Release) } return fmt.Sprintf("com.ubuntu.juju:%s:%s", t.Release, t.Arch), nil diff --git a/internal/cloudconfig/cloudinit/interface.go b/internal/cloudconfig/cloudinit/interface.go index 5daf5763beaf..c929c59f5fa2 100644 --- a/internal/cloudconfig/cloudinit/interface.go +++ b/internal/cloudconfig/cloudinit/interface.go @@ -14,7 +14,7 @@ import ( "golang.org/x/crypto/ssh" corenetwork "github.com/juju/juju/core/network" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" jujupackaging "github.com/juju/juju/internal/packaging" ) @@ -414,7 +414,7 @@ func WithDisableNetplanMACMatch(cfg *cloudConfig) { // New returns a new Config with no options set. func New(osname string, opts ...func(*cloudConfig)) (CloudConfig, error) { - osType := os.OSTypeForName(osname) + osType := ostype.OSTypeForName(osname) r, _ := shell.NewRenderer("bash") cfg := &cloudConfig{ @@ -427,7 +427,7 @@ func New(osname string, opts ...func(*cloudConfig)) (CloudConfig, error) { } switch osType { - case os.Ubuntu: + case ostype.Ubuntu: cfg.paccmder = map[jujupackaging.PackageManagerName]commands.PackageCommander{ jujupackaging.AptPackageManager: commands.NewAptPackageCommander(), jujupackaging.SnapPackageManager: commands.NewSnapPackageCommander(), @@ -436,7 +436,7 @@ func New(osname string, opts ...func(*cloudConfig)) (CloudConfig, error) { jujupackaging.AptPackageManager: config.NewAptPackagingConfigurer(), } return &ubuntuCloudConfig{cfg}, nil - case os.CentOS: + case ostype.CentOS: cfg.paccmder = map[jujupackaging.PackageManagerName]commands.PackageCommander{ jujupackaging.YumPackageManager: commands.NewYumPackageCommander(), } diff --git a/internal/cloudconfig/machinecloudconfig.go b/internal/cloudconfig/machinecloudconfig.go index dff9546ed109..0ff9fb1cb001 100644 --- a/internal/cloudconfig/machinecloudconfig.go +++ b/internal/cloudconfig/machinecloudconfig.go @@ -9,12 +9,12 @@ import ( "github.com/juju/errors" "github.com/juju/loggo/v2" - osseries "github.com/juju/os/v2/series" "github.com/juju/utils/v4" "gopkg.in/yaml.v2" corebase "github.com/juju/juju/core/base" utilsos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/core/paths" ) @@ -80,11 +80,10 @@ func NewMachineInitReaderFromConfig(cfg MachineInitReaderConfig) InitReader { // GetInitConfig returns a map of configuration data used to provision the // machine. It is sourced from both Cloud-Init and Curtin data. func (r *MachineInitReader) GetInitConfig() (map[string]interface{}, error) { - switch utilsos.OSTypeForName(r.config.Base.OS) { - case utilsos.Ubuntu, utilsos.CentOS: - hostSeries, err := osseries.HostSeries() - series, err2 := corebase.GetSeriesFromBase(r.config.Base) - if err != nil || err2 != nil || series != hostSeries { + switch ostype.OSTypeForName(r.config.Base.OS) { + case ostype.Ubuntu, ostype.CentOS: + base, err := utilsos.HostBase() + if err != nil || r.config.Base != base { logger.Debugf("not attempting to get init config for %s, base of machine and container differ", r.config.Base.DisplayString()) return nil, nil } diff --git a/internal/cloudconfig/machinecloudconfig_test.go b/internal/cloudconfig/machinecloudconfig_test.go index c775e7f8dbf4..78622e9af3df 100644 --- a/internal/cloudconfig/machinecloudconfig_test.go +++ b/internal/cloudconfig/machinecloudconfig_test.go @@ -6,12 +6,12 @@ import ( "path/filepath" "github.com/juju/loggo/v2" - utilsseries "github.com/juju/os/v2/series" jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" corebase "github.com/juju/juju/core/base" coreos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig" "github.com/juju/juju/testing" ) @@ -27,7 +27,7 @@ type fromHostSuite struct { var _ = gc.Suite(&fromHostSuite{}) func (s *fromHostSuite) SetUpTest(c *gc.C) { - s.PatchValue(&utilsseries.HostSeries, func() (string, error) { return "jammy", nil }) + s.PatchValue(&coreos.HostBase, func() (corebase.Base, error) { return corebase.ParseBaseFromString("ubuntu@22.04") }) // Pre-seed /etc/cloud/cloud.cfg.d replacement for testing s.tempCloudCfgDir = c.MkDir() // will clean up @@ -88,9 +88,7 @@ var cloudinitDataVerifyTests = []cloudinitDataVerifyTest{ func (s *fromHostSuite) TestGetMachineCloudInitDataVerifySeries(c *gc.C) { for i, test := range cloudinitDataVerifyTests { c.Logf("Test %d of %d: %s", i, len(cloudinitDataVerifyTests), test.description) - machineSeries, err := corebase.GetSeriesFromBase(test.machineBase) - c.Assert(err, jc.ErrorIsNil) - s.PatchValue(&utilsseries.HostSeries, func() (string, error) { return machineSeries, nil }) + s.PatchValue(&coreos.HostBase, func() (corebase.Base, error) { return test.machineBase, nil }) obtained, err := s.newMachineInitReader(test.containerBase).GetInitConfig() c.Assert(err, gc.IsNil) if test.result != nil { @@ -159,7 +157,7 @@ func (s *fromHostSuite) TestCloudConfigVersionNoContainerInheritProperties(c *gc } func (s *fromHostSuite) TestCurtinConfigAptProperties(c *gc.C) { - s.PatchValue(&coreos.HostOS, func() coreos.OSType { return coreos.Ubuntu }) + s.PatchValue(&coreos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) // Seed the curtin install config as for MAAS 2.5+ curtinDir := c.MkDir() diff --git a/internal/cloudconfig/providerinit/providerinit.go b/internal/cloudconfig/providerinit/providerinit.go index 34b313360645..04a625364921 100644 --- a/internal/cloudconfig/providerinit/providerinit.go +++ b/internal/cloudconfig/providerinit/providerinit.go @@ -8,7 +8,7 @@ import ( "github.com/juju/errors" "github.com/juju/loggo/v2" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig" "github.com/juju/juju/internal/cloudconfig/cloudinit" "github.com/juju/juju/internal/cloudconfig/instancecfg" @@ -61,7 +61,7 @@ func ComposeUserData(icfg *instancecfg.InstanceConfig, cloudcfg cloudinit.CloudC if err != nil { return nil, errors.Trace(err) } - udata, err := renderer.Render(cloudcfg, os.OSTypeForName(icfg.Base.OS)) + udata, err := renderer.Render(cloudcfg, ostype.OSTypeForName(icfg.Base.OS)) if err != nil { return nil, errors.Trace(err) } diff --git a/internal/cloudconfig/providerinit/renderers/interface.go b/internal/cloudconfig/providerinit/renderers/interface.go index 910ddba60559..bcfe0d763cb5 100644 --- a/internal/cloudconfig/providerinit/renderers/interface.go +++ b/internal/cloudconfig/providerinit/renderers/interface.go @@ -5,7 +5,7 @@ package renderers import ( - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit" ) @@ -15,5 +15,5 @@ import ( // the userdata differently(bash vs yaml) since some providers might // not ship cloudinit on every OS type ProviderRenderer interface { - Render(cloudinit.CloudConfig, os.OSType) ([]byte, error) + Render(cloudinit.CloudConfig, ostype.OSType) ([]byte, error) } diff --git a/internal/cloudconfig/userdatacfg.go b/internal/cloudconfig/userdatacfg.go index f90b676a1b3d..1c3fc586827a 100644 --- a/internal/cloudconfig/userdatacfg.go +++ b/internal/cloudconfig/userdatacfg.go @@ -13,7 +13,7 @@ import ( "github.com/juju/utils/v4" "github.com/juju/juju/agent" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit" "github.com/juju/juju/internal/cloudconfig/instancecfg" ) @@ -59,7 +59,7 @@ type UserdataConfig interface { func NewUserdataConfig(icfg *instancecfg.InstanceConfig, conf cloudinit.CloudConfig) (UserdataConfig, error) { // TODO(ericsnow) bug #1426217 // Protect icfg and conf better. - operatingSystem := os.OSTypeForName(icfg.Base.OS) + operatingSystem := ostype.OSTypeForName(icfg.Base.OS) base := baseConfigure{ tag: names.NewMachineTag(icfg.MachineId), icfg: icfg, @@ -68,9 +68,9 @@ func NewUserdataConfig(icfg *instancecfg.InstanceConfig, conf cloudinit.CloudCon } switch operatingSystem { - case os.Ubuntu: + case ostype.Ubuntu: return &unixConfigure{base}, nil - case os.CentOS: + case ostype.CentOS: return &unixConfigure{base}, nil default: return nil, errors.NotSupportedf("OS %s", icfg.Base.OS) @@ -81,7 +81,7 @@ type baseConfigure struct { tag names.Tag icfg *instancecfg.InstanceConfig conf cloudinit.CloudConfig - os os.OSType + os ostype.OSType } // addAgentInfo adds agent-required information to the agent's directory @@ -134,12 +134,12 @@ func (c *baseConfigure) addMachineAgentToBoot() error { // It may make sense in the future to add a "juju" user instead across // all distributions. func SetUbuntuUser(conf cloudinit.CloudConfig, authorizedKeys string) { - targetOS := os.OSTypeForName(conf.GetOS()) + targetOS := ostype.OSTypeForName(conf.GetOS()) var groups []string switch targetOS { - case os.Ubuntu: + case ostype.Ubuntu: groups = UbuntuGroups - case os.CentOS: + case ostype.CentOS: groups = CentOSGroups } conf.AddUser(&cloudinit.User{ diff --git a/internal/cloudconfig/userdatacfg_unix.go b/internal/cloudconfig/userdatacfg_unix.go index 9e3f91fe04a4..8ac46cda5bca 100644 --- a/internal/cloudconfig/userdatacfg_unix.go +++ b/internal/cloudconfig/userdatacfg_unix.go @@ -23,7 +23,7 @@ import ( "github.com/juju/utils/v4" "github.com/juju/juju/agent" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs/bootstrap" "github.com/juju/juju/environs/simplestreams" "github.com/juju/juju/internal/cloudconfig/cloudinit" @@ -175,7 +175,7 @@ func (w *unixConfigure) ConfigureBasic() error { "set -xe", // ensure we run all the scripts or abort. ) switch w.os { - case os.CentOS: + case ostype.CentOS: w.conf.AddScripts( // Mask and stop firewalld, if enabled, so it cannot start. See // http://pad.lv/1492066. firewalld might be missing, in which case @@ -223,7 +223,7 @@ func (w *unixConfigure) ConfigureBasic() error { func (w *unixConfigure) setDataDirPermissions() string { var user string switch w.os { - case os.CentOS: + case ostype.CentOS: user = "root" default: user = "syslog" diff --git a/internal/container/lxd/export_test.go b/internal/container/lxd/export_test.go index 1379ca35b83d..fcb703763c21 100644 --- a/internal/container/lxd/export_test.go +++ b/internal/container/lxd/export_test.go @@ -10,6 +10,7 @@ import ( lxdclient "github.com/canonical/lxd/client" "github.com/juju/clock" + "github.com/juju/juju/core/base" "github.com/juju/juju/core/network" "github.com/juju/juju/internal/container" ) @@ -45,8 +46,8 @@ func PatchLXDViaSnap(patcher patcher, isSnap bool) { patcher.PatchValue(&lxdViaSnap, func() bool { return isSnap }) } -func PatchHostSeries(patcher patcher, series string) { - patcher.PatchValue(&hostSeries, func() (string, error) { return series, nil }) +func PatchHostBase(patcher patcher, b base.Base) { + patcher.PatchValue(&hostBase, func() (base.Base, error) { return b, nil }) } func PatchGetSnapManager(patcher patcher, mgr SnapManager) { diff --git a/internal/container/lxd/image.go b/internal/container/lxd/image.go index 6246d64102a6..b926371d1a8a 100644 --- a/internal/container/lxd/image.go +++ b/internal/container/lxd/image.go @@ -18,7 +18,7 @@ import ( jujuarch "github.com/juju/juju/core/arch" jujubase "github.com/juju/juju/core/base" "github.com/juju/juju/core/instance" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/core/status" "github.com/juju/juju/environs" ) @@ -244,11 +244,11 @@ func isCompatibleVirtType(virtType instance.VirtType, instanceType string) bool } func constructBaseRemoteAlias(base jujubase.Base, arch string) (string, error) { - seriesOS := jujuos.OSTypeForName(base.OS) + seriesOS := ostype.OSTypeForName(base.OS) switch seriesOS { - case jujuos.Ubuntu: + case ostype.Ubuntu: return path.Join(base.Channel.Track, arch), nil - case jujuos.CentOS: + case ostype.CentOS: if arch == jujuarch.AMD64 { switch base.Channel.Track { case "7", "8": diff --git a/internal/container/lxd/initialisation_linux.go b/internal/container/lxd/initialisation_linux.go index d00a5e564e23..874670bfb007 100644 --- a/internal/container/lxd/initialisation_linux.go +++ b/internal/container/lxd/initialisation_linux.go @@ -11,18 +11,18 @@ import ( "time" "github.com/juju/errors" - "github.com/juju/os/v2/series" "github.com/juju/packaging/v3/manager" "github.com/juju/proxy" corebase "github.com/juju/juju/core/base" + coreos "github.com/juju/juju/core/os" "github.com/juju/juju/internal/container" "github.com/juju/juju/internal/packaging" "github.com/juju/juju/internal/packaging/dependency" "github.com/juju/juju/internal/service" ) -var hostSeries = series.HostSeries +var hostBase = coreos.HostBase type containerInitialiser struct { containerNetworkingMethod string @@ -68,11 +68,7 @@ func NewContainerInitialiser(lxdSnapChannel, containerNetworkingMethod string) c // Initialise is specified on the container.Initialiser interface. func (ci *containerInitialiser) Initialise() (err error) { - localSeries, err := hostSeries() - if err != nil { - return errors.Trace(err) - } - localBase, err := corebase.GetBaseFromSeries(localSeries) + localBase, err := hostBase() if err != nil { return errors.Trace(err) } diff --git a/internal/container/lxd/initialisation_test.go b/internal/container/lxd/initialisation_test.go index fff3d781bed4..9064b1705742 100644 --- a/internal/container/lxd/initialisation_test.go +++ b/internal/container/lxd/initialisation_test.go @@ -18,6 +18,7 @@ import ( "go.uber.org/mock/gomock" gc "gopkg.in/check.v1" + "github.com/juju/juju/core/base" "github.com/juju/juju/internal/container/lxd/mocks" lxdtesting "github.com/juju/juju/internal/container/lxd/testing" coretesting "github.com/juju/juju/testing" @@ -86,7 +87,7 @@ func (s *initialiserTestSuite) containerInitialiser(svr lxd.InstanceServer, lxdI func (s *InitialiserSuite) TestSnapInstalled(c *gc.C) { PatchLXDViaSnap(s, true) - PatchHostSeries(s, "jammy") + PatchHostBase(s, base.MustParseBaseFromString("ubuntu@22.04")) ctrl := gomock.NewController(c) defer ctrl.Finish() @@ -103,7 +104,7 @@ func (s *InitialiserSuite) TestSnapInstalled(c *gc.C) { func (s *InitialiserSuite) TestSnapChannelMismatch(c *gc.C) { PatchLXDViaSnap(s, true) - PatchHostSeries(s, "focal") + PatchHostBase(s, base.MustParseBaseFromString("ubuntu@20.04")) ctrl := gomock.NewController(c) defer ctrl.Finish() @@ -121,7 +122,7 @@ func (s *InitialiserSuite) TestSnapChannelMismatch(c *gc.C) { func (s *InitialiserSuite) TestSnapChannelPrefixMatch(c *gc.C) { PatchLXDViaSnap(s, true) - PatchHostSeries(s, "focal") + PatchHostBase(s, base.MustParseBaseFromString("ubuntu@20.04")) ctrl := gomock.NewController(c) defer ctrl.Finish() @@ -143,7 +144,7 @@ func (s *InitialiserSuite) TestSnapChannelPrefixMatch(c *gc.C) { func (s *InitialiserSuite) TestInstallViaSnap(c *gc.C) { PatchLXDViaSnap(s, false) - PatchHostSeries(s, "focal") + PatchHostBase(s, base.MustParseBaseFromString("ubuntu@20.04")) paccmder := commands.NewSnapPackageCommander() @@ -157,7 +158,7 @@ func (s *InitialiserSuite) TestInstallViaSnap(c *gc.C) { func (s *InitialiserSuite) TestLXDAlreadyInitialized(c *gc.C) { s.patchDF100GB() - PatchHostSeries(s, "focal") + PatchHostBase(s, base.MustParseBaseFromString("ubuntu@20.04")) ci := s.containerInitialiser(nil, true, "local") ci.getExecCommand = s.PatchExecHelper.GetExecCommand(testing.PatchExecConfig{ @@ -171,7 +172,7 @@ func (s *InitialiserSuite) TestLXDAlreadyInitialized(c *gc.C) { } func (s *InitialiserSuite) TestInitializeSetsProxies(c *gc.C) { - PatchHostSeries(s, "jammy") + PatchHostBase(s, base.MustParseBaseFromString("ubuntu@20.04")) ctrl := gomock.NewController(c) defer ctrl.Finish() diff --git a/internal/mongo/mongo.go b/internal/mongo/mongo.go index 00eaf69c1790..a6227647d71c 100644 --- a/internal/mongo/mongo.go +++ b/internal/mongo/mongo.go @@ -20,13 +20,13 @@ import ( "github.com/juju/errors" "github.com/juju/loggo/v2" "github.com/juju/mgo/v3" - "github.com/juju/os/v2/series" "github.com/juju/replicaset/v3" "github.com/juju/retry" "github.com/juju/utils/v4" "github.com/juju/juju/core/base" "github.com/juju/juju/core/network" + coreos "github.com/juju/juju/core/os" "github.com/juju/juju/internal/packaging" "github.com/juju/juju/internal/packaging/dependency" "github.com/juju/juju/internal/service/common" @@ -225,15 +225,6 @@ func EnsureServerInstalled(ctx context.Context, args EnsureServerParams) error { func ensureServer(ctx context.Context, args EnsureServerParams, mongoKernelTweaks map[string]string) (err error) { tweakSysctlForMongo(mongoKernelTweaks) - hostSeries, err := series.HostSeries() - if err != nil { - return errors.Annotatef(err, "cannot get host series") - } - hostBase, err := base.GetBaseFromSeries(hostSeries) - if err != nil { - return errors.Annotatef(err, "host series %q not a vlaid base", hostSeries) - } - mongoDep := dependency.Mongo(args.JujuDBSnapChannel) if args.DataDir == "" { args.DataDir = dataPathForJujuDbSnap @@ -257,6 +248,11 @@ func ensureServer(ctx context.Context, args EnsureServerParams, mongoKernelTweak return errors.Annotatef(err, "cannot create mongo snap service") } + hostBase, err := coreos.HostBase() + if err != nil { + return errors.Annotatef(err, "cannot get host base") + } + if err := installMongod(mongoDep, hostBase, svc); err != nil { return errors.Annotatef(err, "cannot install mongod") } diff --git a/internal/provider/azure/environ.go b/internal/provider/azure/environ.go index 72d468761de5..4937aa4eea80 100644 --- a/internal/provider/azure/environ.go +++ b/internal/provider/azure/environ.go @@ -30,7 +30,7 @@ import ( "github.com/juju/juju/core/arch" "github.com/juju/juju/core/constraints" "github.com/juju/juju/core/instance" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs" environscloudspec "github.com/juju/juju/environs/cloudspec" "github.com/juju/juju/environs/config" @@ -843,7 +843,7 @@ func (env *azureEnviron) createVirtualMachine( // On CentOS, we must add the CustomScript VM extension to run the // CustomData script. - if seriesOS == os.CentOS { + if seriesOS == ostype.CentOS { properties, err := vmExtensionProperties(seriesOS) if err != nil { return errors.Annotate( @@ -1068,12 +1068,12 @@ func newOSProfile( vmName string, instanceConfig *instancecfg.InstanceConfig, generateSSHKey func(string) (string, string, error), -) (*armcompute.OSProfile, os.OSType, error) { +) (*armcompute.OSProfile, ostype.OSType, error) { logger.Debugf("creating OS profile for %q", vmName) customData, err := providerinit.ComposeUserData(instanceConfig, nil, AzureRenderer{}) if err != nil { - return nil, os.Unknown, errors.Annotate(err, "composing user data") + return nil, ostype.Unknown, errors.Annotate(err, "composing user data") } osProfile := &armcompute.OSProfile{ @@ -1081,12 +1081,12 @@ func newOSProfile( CustomData: to.Ptr(string(customData)), } - instOS := os.OSTypeForName(instanceConfig.Base.OS) + instOS := ostype.OSTypeForName(instanceConfig.Base.OS) if err != nil { - return nil, os.Unknown, errors.Trace(err) + return nil, ostype.Unknown, errors.Trace(err) } switch instOS { - case os.Ubuntu, os.CentOS: + case ostype.Ubuntu, ostype.CentOS: // SSH keys are handled by custom data, but must also be // specified in order to forego providing a password, and // disable password authentication. @@ -1100,7 +1100,7 @@ func newOSProfile( // are updated with one that Juju tracks. _, public, err := generateSSHKey("") if err != nil { - return nil, os.Unknown, errors.Trace(err) + return nil, ostype.Unknown, errors.Trace(err) } authorizedKeys = public } @@ -1115,7 +1115,7 @@ func newOSProfile( SSH: &armcompute.SSHConfiguration{PublicKeys: publicKeys}, } default: - return nil, os.Unknown, errors.NotSupportedf("%s", instOS) + return nil, ostype.Unknown, errors.NotSupportedf("%s", instOS) } return osProfile, instOS, nil } diff --git a/internal/provider/azure/internal/imageutils/images.go b/internal/provider/azure/internal/imageutils/images.go index 6ed7ca46a4c8..0f13e23a09a7 100644 --- a/internal/provider/azure/internal/imageutils/images.go +++ b/internal/provider/azure/internal/imageutils/images.go @@ -15,8 +15,7 @@ import ( "github.com/juju/juju/core/arch" jujubase "github.com/juju/juju/core/base" - "github.com/juju/juju/core/os" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs/envcontext" "github.com/juju/juju/environs/imagemetadata" "github.com/juju/juju/environs/instances" @@ -45,11 +44,11 @@ func SeriesImage( base jujubase.Base, stream, location string, client *armcompute.VirtualMachineImagesClient, ) (*instances.Image, error) { - seriesOS := jujuos.OSTypeForName(base.OS) + seriesOS := ostype.OSTypeForName(base.OS) var publisher, offering, sku string switch seriesOS { - case os.Ubuntu: + case ostype.Ubuntu: series, err := jujubase.GetSeriesFromBase(base) if err != nil { return nil, errors.Trace(err) @@ -60,7 +59,7 @@ func SeriesImage( return nil, errors.Annotatef(err, "selecting SKU for %s", base.DisplayString()) } - case os.CentOS: + case ostype.CentOS: publisher = centOSPublisher offering = centOSOffering switch base.Channel.Track { diff --git a/internal/provider/azure/userdata.go b/internal/provider/azure/userdata.go index 886fc84c3533..8f734ff54ef9 100644 --- a/internal/provider/azure/userdata.go +++ b/internal/provider/azure/userdata.go @@ -8,18 +8,18 @@ import ( "github.com/juju/errors" "github.com/juju/utils/v4" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit" "github.com/juju/juju/internal/cloudconfig/providerinit/renderers" ) type AzureRenderer struct{} -func (AzureRenderer) Render(cfg cloudinit.CloudConfig, os jujuos.OSType) ([]byte, error) { +func (AzureRenderer) Render(cfg cloudinit.CloudConfig, os ostype.OSType) ([]byte, error) { switch os { - case jujuos.Ubuntu: + case ostype.Ubuntu: return renderers.RenderYAML(cfg, utils.Gzip, renderers.ToBase64) - case jujuos.CentOS: + case ostype.CentOS: return renderers.RenderScript(cfg, renderers.ToBase64) default: return nil, errors.Errorf("Cannot encode userdata for OS: %s", os) diff --git a/internal/provider/azure/vmextension.go b/internal/provider/azure/vmextension.go index 33fddc41dc36..6adee0e9a0ea 100644 --- a/internal/provider/azure/vmextension.go +++ b/internal/provider/azure/vmextension.go @@ -8,7 +8,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v2" "github.com/juju/errors" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" ) const extensionName = "JujuCustomScriptExtension" @@ -24,11 +24,11 @@ const ( // vmExtension creates a CustomScript VM extension for the given VM // which will execute the CustomData on the machine as a script. -func vmExtensionProperties(os jujuos.OSType) (*armcompute.VirtualMachineExtensionProperties, error) { +func vmExtensionProperties(os ostype.OSType) (*armcompute.VirtualMachineExtensionProperties, error) { var commandToExecute, extensionPublisher, extensionType, extensionVersion string switch os { - case jujuos.CentOS: + case ostype.CentOS: commandToExecute = linuxExecuteCustomScriptCommand extensionPublisher = linuxCustomScriptPublisher extensionType = linuxCustomScriptType diff --git a/internal/provider/common/disk.go b/internal/provider/common/disk.go index 8cab4faa349d..eb70b501da5f 100644 --- a/internal/provider/common/disk.go +++ b/internal/provider/common/disk.go @@ -3,15 +3,13 @@ package common -import ( - jujuos "github.com/juju/juju/core/os" -) +import "github.com/juju/juju/core/os/ostype" // MinRootDiskSizeGiB is the minimum size for the root disk of an // instance, in Gigabytes. This value accommodates the anticipated // size of the initial image, any updates, and future application // data. -func MinRootDiskSizeGiB(_ jujuos.OSType) uint64 { +func MinRootDiskSizeGiB(_ ostype.OSType) uint64 { return 8 } diff --git a/internal/provider/common/disk_test.go b/internal/provider/common/disk_test.go index 4fe4bedd0e0c..1b73aaf52240 100644 --- a/internal/provider/common/disk_test.go +++ b/internal/provider/common/disk_test.go @@ -6,7 +6,7 @@ package common_test import ( gc "gopkg.in/check.v1" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/provider/common" ) @@ -23,7 +23,7 @@ func (s *DiskSuite) TestMinRootDiskSizeGiB(c *gc.C) { {"centos", 8}, } for _, t := range diskTests { - actualSize := common.MinRootDiskSizeGiB(os.OSTypeForName(t.osname)) + actualSize := common.MinRootDiskSizeGiB(ostype.OSTypeForName(t.osname)) c.Assert(t.expectedSize, gc.Equals, actualSize) } } diff --git a/internal/provider/ec2/ebs.go b/internal/provider/ec2/ebs.go index f9aac7a241c8..95abb2fb93af 100644 --- a/internal/provider/ec2/ebs.go +++ b/internal/provider/ec2/ebs.go @@ -23,7 +23,7 @@ import ( "github.com/juju/juju/core/constraints" "github.com/juju/juju/core/instance" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs/envcontext" "github.com/juju/juju/environs/tags" "github.com/juju/juju/internal/provider/common" @@ -1106,7 +1106,7 @@ func blockDeviceNamer(numbers bool) func() (requestName, actualName string, err } func minRootDiskSizeMiB(osname string) uint64 { - return gibToMib(common.MinRootDiskSizeGiB(os.OSTypeForName(osname))) + return gibToMib(common.MinRootDiskSizeGiB(ostype.OSTypeForName(osname))) } // getBlockDeviceMappings translates constraints into BlockDeviceMappings. diff --git a/internal/provider/ec2/userdata.go b/internal/provider/ec2/userdata.go index 87348738745d..b82ade5a4e81 100644 --- a/internal/provider/ec2/userdata.go +++ b/internal/provider/ec2/userdata.go @@ -8,16 +8,16 @@ import ( "github.com/juju/errors" "github.com/juju/utils/v4" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit" "github.com/juju/juju/internal/cloudconfig/providerinit/renderers" ) type AmazonRenderer struct{} -func (AmazonRenderer) Render(cfg cloudinit.CloudConfig, os jujuos.OSType) ([]byte, error) { +func (AmazonRenderer) Render(cfg cloudinit.CloudConfig, os ostype.OSType) ([]byte, error) { switch os { - case jujuos.Ubuntu, jujuos.CentOS: + case ostype.Ubuntu, ostype.CentOS: return renderers.RenderYAML(cfg, utils.Gzip) default: return nil, errors.Errorf("Cannot encode userdata for OS: %s", os.String()) diff --git a/internal/provider/ec2/userdata_test.go b/internal/provider/ec2/userdata_test.go index f5286513a098..dd486d395be5 100644 --- a/internal/provider/ec2/userdata_test.go +++ b/internal/provider/ec2/userdata_test.go @@ -9,7 +9,7 @@ import ( "github.com/juju/utils/v4" gc "gopkg.in/check.v1" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit/cloudinittest" "github.com/juju/juju/internal/provider/ec2" "github.com/juju/juju/testing" @@ -25,11 +25,11 @@ func (s *UserdataSuite) TestAmazonUnix(c *gc.C) { renderer := ec2.AmazonRenderer{} cloudcfg := &cloudinittest.CloudConfig{YAML: []byte("yaml")} - result, err := renderer.Render(cloudcfg, os.Ubuntu) + result, err := renderer.Render(cloudcfg, ostype.Ubuntu) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, utils.Gzip(cloudcfg.YAML)) - result, err = renderer.Render(cloudcfg, os.CentOS) + result, err = renderer.Render(cloudcfg, ostype.CentOS) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, utils.Gzip(cloudcfg.YAML)) } @@ -37,7 +37,7 @@ func (s *UserdataSuite) TestAmazonUnix(c *gc.C) { func (s *UserdataSuite) TestAmazonUnknownOS(c *gc.C) { renderer := ec2.AmazonRenderer{} cloudcfg := &cloudinittest.CloudConfig{} - result, err := renderer.Render(cloudcfg, os.GenericLinux) + result, err := renderer.Render(cloudcfg, ostype.GenericLinux) c.Assert(result, gc.IsNil) c.Assert(err, gc.ErrorMatches, "Cannot encode userdata for OS: GenericLinux") } diff --git a/internal/provider/equinix/userdata.go b/internal/provider/equinix/userdata.go index ca9c23eb0679..b61d60896afd 100644 --- a/internal/provider/equinix/userdata.go +++ b/internal/provider/equinix/userdata.go @@ -6,16 +6,16 @@ package equinix import ( "github.com/juju/errors" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit" "github.com/juju/juju/internal/cloudconfig/providerinit/renderers" ) type EquinixRenderer struct{} -func (EquinixRenderer) Render(cfg cloudinit.CloudConfig, os jujuos.OSType) ([]byte, error) { +func (EquinixRenderer) Render(cfg cloudinit.CloudConfig, os ostype.OSType) ([]byte, error) { switch os { - case jujuos.Ubuntu, jujuos.CentOS: + case ostype.Ubuntu, ostype.CentOS: return renderers.RenderYAML(cfg) default: return nil, errors.Errorf("Cannot encode userdata for OS: %s", os.String()) diff --git a/internal/provider/gce/environ_broker.go b/internal/provider/gce/environ_broker.go index d8023172b349..ae6d94e44440 100644 --- a/internal/provider/gce/environ_broker.go +++ b/internal/provider/gce/environ_broker.go @@ -10,7 +10,7 @@ import ( "github.com/juju/juju/core/constraints" "github.com/juju/juju/core/instance" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs" "github.com/juju/juju/environs/envcontext" "github.com/juju/juju/environs/imagemetadata" @@ -128,14 +128,14 @@ func (env *environ) findInstanceSpec( return spec, errors.Trace(err) } -func (env *environ) imageURLBase(os jujuos.OSType) (string, error) { +func (env *environ) imageURLBase(os ostype.OSType) (string, error) { base, useCustomPath := env.ecfg.baseImagePath() if useCustomPath { return base, nil } switch os { - case jujuos.Ubuntu: + case ostype.Ubuntu: switch env.Config().ImageStream() { case "daily": base = ubuntuDailyImageBasePath @@ -162,7 +162,7 @@ func (env *environ) newRawInstance( return nil, environs.ZoneIndependentError(err) } - os := jujuos.OSTypeForName(args.InstanceConfig.Base.OS) + os := ostype.OSTypeForName(args.InstanceConfig.Base.OS) metadata, err := getMetadata(args, os) if err != nil { return nil, environs.ZoneIndependentError(err) @@ -214,7 +214,7 @@ func (env *environ) newRawInstance( // getMetadata builds the raw "user-defined" metadata for the new // instance (relative to the provided args) and returns it. -func getMetadata(args environs.StartInstanceParams, os jujuos.OSType) (map[string]string, error) { +func getMetadata(args environs.StartInstanceParams, os ostype.OSType) (map[string]string, error) { userData, err := providerinit.ComposeUserData(args.InstanceConfig, nil, GCERenderer{}) if err != nil { return nil, errors.Annotate(err, "cannot make user data") @@ -226,7 +226,7 @@ func getMetadata(args environs.StartInstanceParams, os jujuos.OSType) (map[strin metadata[tag] = value } switch os { - case jujuos.Ubuntu: + case ostype.Ubuntu: // We store a gz snapshop of information that is used by // cloud-init and unpacked in to the /var/lib/cloud/instances folder // for the instance. Due to a limitation with GCE and binary blobs @@ -247,7 +247,7 @@ func getMetadata(args environs.StartInstanceParams, os jujuos.OSType) (map[strin // the new instances and returns it. This will always include a root // disk with characteristics determined by the provides args and // constraints. -func getDisks(spec *instances.InstanceSpec, cons constraints.Value, os jujuos.OSType, eUUID string, imageURLBase string) ([]google.DiskSpec, error) { +func getDisks(spec *instances.InstanceSpec, cons constraints.Value, os ostype.OSType, eUUID string, imageURLBase string) ([]google.DiskSpec, error) { size := common.MinRootDiskSizeGiB(os) if cons.RootDisk != nil && *cons.RootDisk > size { size = common.MiBToGiB(*cons.RootDisk) diff --git a/internal/provider/gce/environ_broker_test.go b/internal/provider/gce/environ_broker_test.go index 837b0a894a94..b41a3e651d31 100644 --- a/internal/provider/gce/environ_broker_test.go +++ b/internal/provider/gce/environ_broker_test.go @@ -13,7 +13,7 @@ import ( "github.com/juju/juju/core/arch" corebase "github.com/juju/juju/core/base" "github.com/juju/juju/core/instance" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs" "github.com/juju/juju/environs/imagemetadata" "github.com/juju/juju/environs/instances" @@ -201,7 +201,7 @@ func (s *environBrokerSuite) TestNewRawInstanceZoneSpecificError(c *gc.C) { } func (s *environBrokerSuite) TestGetMetadataUbuntu(c *gc.C) { - metadata, err := gce.GetMetadata(s.StartInstArgs, jujuos.Ubuntu) + metadata, err := gce.GetMetadata(s.StartInstArgs, ostype.Ubuntu) c.Assert(err, jc.ErrorIsNil) c.Check(metadata, jc.DeepEquals, s.UbuntuMetadata) @@ -209,7 +209,7 @@ func (s *environBrokerSuite) TestGetMetadataUbuntu(c *gc.C) { } func (s *environBrokerSuite) TestGetMetadataOSNotSupported(c *gc.C) { - metadata, err := gce.GetMetadata(s.StartInstArgs, jujuos.GenericLinux) + metadata, err := gce.GetMetadata(s.StartInstArgs, ostype.GenericLinux) c.Assert(metadata, gc.IsNil) c.Assert(err, gc.ErrorMatches, "cannot pack metadata for os GenericLinux on the gce provider") @@ -227,7 +227,7 @@ var getDisksTests = []struct { func (s *environBrokerSuite) TestGetDisks(c *gc.C) { for _, test := range getDisksTests { - os := jujuos.OSTypeForName(test.osname) + os := ostype.OSTypeForName(test.osname) diskSpecs, err := gce.GetDisks(s.spec, s.StartInstArgs.Constraints, os, "32f7d570-5bac-4b72-b169-250c24a94b2b", test.basePath) if test.error != nil { c.Assert(err, gc.Equals, err) @@ -238,9 +238,9 @@ func (s *environBrokerSuite) TestGetDisks(c *gc.C) { diskSpec := diskSpecs[0] switch os { - case jujuos.Ubuntu: + case ostype.Ubuntu: c.Check(diskSpec.SizeHintGB, gc.Equals, uint64(8)) - case jujuos.Windows: + case ostype.Windows: c.Check(diskSpec.SizeHintGB, gc.Equals, uint64(40)) default: c.Check(diskSpec.SizeHintGB, gc.Equals, uint64(8)) @@ -249,7 +249,7 @@ func (s *environBrokerSuite) TestGetDisks(c *gc.C) { } } - diskSpecs, err := gce.GetDisks(s.spec, s.StartInstArgs.Constraints, jujuos.Ubuntu, "32f7d570-5bac-4b72-b169-250c24a94b2b", gce.UbuntuDailyImageBasePath) + diskSpecs, err := gce.GetDisks(s.spec, s.StartInstArgs.Constraints, ostype.Ubuntu, "32f7d570-5bac-4b72-b169-250c24a94b2b", gce.UbuntuDailyImageBasePath) c.Assert(err, jc.ErrorIsNil) c.Assert(diskSpecs, gc.HasLen, 1) spec := diskSpecs[0] diff --git a/internal/provider/gce/userdata.go b/internal/provider/gce/userdata.go index b0eed69da0cc..cf0e295b90de 100644 --- a/internal/provider/gce/userdata.go +++ b/internal/provider/gce/userdata.go @@ -8,16 +8,16 @@ import ( "github.com/juju/errors" "github.com/juju/utils/v4" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit" "github.com/juju/juju/internal/cloudconfig/providerinit/renderers" ) type GCERenderer struct{} -func (GCERenderer) Render(cfg cloudinit.CloudConfig, os jujuos.OSType) ([]byte, error) { +func (GCERenderer) Render(cfg cloudinit.CloudConfig, os ostype.OSType) ([]byte, error) { switch os { - case jujuos.Ubuntu, jujuos.CentOS: + case ostype.Ubuntu, ostype.CentOS: return renderers.RenderYAML(cfg, utils.Gzip, renderers.ToBase64) default: return nil, errors.Errorf("Cannot encode userdata for OS: %s", os.String()) diff --git a/internal/provider/gce/userdata_test.go b/internal/provider/gce/userdata_test.go index f82655188adc..9d31571edba5 100644 --- a/internal/provider/gce/userdata_test.go +++ b/internal/provider/gce/userdata_test.go @@ -11,7 +11,7 @@ import ( "github.com/juju/utils/v4" gc "gopkg.in/check.v1" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit/cloudinittest" "github.com/juju/juju/internal/provider/gce" "github.com/juju/juju/testing" @@ -27,12 +27,12 @@ func (s *UserdataSuite) TestGCEUnix(c *gc.C) { renderer := gce.GCERenderer{} cloudcfg := &cloudinittest.CloudConfig{YAML: []byte("yaml")} - result, err := renderer.Render(cloudcfg, os.Ubuntu) + result, err := renderer.Render(cloudcfg, ostype.Ubuntu) c.Assert(err, jc.ErrorIsNil) expected := base64.StdEncoding.EncodeToString(utils.Gzip(cloudcfg.YAML)) c.Assert(string(result), jc.DeepEquals, expected) - result, err = renderer.Render(cloudcfg, os.CentOS) + result, err = renderer.Render(cloudcfg, ostype.CentOS) c.Assert(err, jc.ErrorIsNil) expected = base64.StdEncoding.EncodeToString(utils.Gzip(cloudcfg.YAML)) c.Assert(string(result), jc.DeepEquals, expected) @@ -42,7 +42,7 @@ func (s *UserdataSuite) TestGCEUnknownOS(c *gc.C) { renderer := gce.GCERenderer{} cloudcfg := &cloudinittest.CloudConfig{} - result, err := renderer.Render(cloudcfg, os.GenericLinux) + result, err := renderer.Render(cloudcfg, ostype.GenericLinux) c.Assert(result, gc.IsNil) c.Assert(err, gc.ErrorMatches, "Cannot encode userdata for OS: GenericLinux") } diff --git a/internal/provider/lxd/environ.go b/internal/provider/lxd/environ.go index 643ccdeaf8e7..e7f60c0ceb87 100644 --- a/internal/provider/lxd/environ.go +++ b/internal/provider/lxd/environ.go @@ -15,6 +15,7 @@ import ( "github.com/juju/errors" "github.com/juju/juju/core/arch" + "github.com/juju/juju/core/base" "github.com/juju/juju/core/instance" "github.com/juju/juju/core/lxdprofile" "github.com/juju/juju/core/network" @@ -461,9 +462,9 @@ func (env *environ) AssignLXDProfiles(instID string, profilesNames []string, pro return report(nil) } -// DetectSeries is a no-op for lxd, must return an empty string. -func (env *environ) DetectSeries() (string, error) { - return "", nil +// DetectBase is a no-op for lxd, must return an empty string. +func (env *environ) DetectBase() (base.Base, error) { + return base.Base{}, nil } // DetectHardware returns the hardware characteristics for the controller for diff --git a/internal/provider/lxd/userdata.go b/internal/provider/lxd/userdata.go index 0d129b5b8be5..6ed27e62df9e 100644 --- a/internal/provider/lxd/userdata.go +++ b/internal/provider/lxd/userdata.go @@ -6,7 +6,7 @@ package lxd import ( "github.com/juju/errors" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit" "github.com/juju/juju/internal/cloudconfig/providerinit/renderers" ) @@ -14,9 +14,9 @@ import ( type lxdRenderer struct{} // EncodeUserdata implements renderers.ProviderRenderer. -func (lxdRenderer) Render(cfg cloudinit.CloudConfig, os jujuos.OSType) ([]byte, error) { +func (lxdRenderer) Render(cfg cloudinit.CloudConfig, os ostype.OSType) ([]byte, error) { switch os { - case jujuos.Ubuntu, jujuos.CentOS: + case ostype.Ubuntu, ostype.CentOS: bytes, err := renderers.RenderYAML(cfg) return bytes, errors.Trace(err) default: diff --git a/internal/provider/maas/environ.go b/internal/provider/maas/environ.go index 30e353e8dfcd..0bce5841745e 100644 --- a/internal/provider/maas/environ.go +++ b/internal/provider/maas/environ.go @@ -25,7 +25,7 @@ import ( "github.com/juju/juju/core/constraints" "github.com/juju/juju/core/instance" corenetwork "github.com/juju/juju/core/network" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/core/status" "github.com/juju/juju/environs" environscloudspec "github.com/juju/juju/environs/cloudspec" @@ -923,9 +923,9 @@ func (env *maasEnviron) newCloudinitConfig(hostname, osname string) (cloudinit.C return nil, errors.Trace(err) } - operatingSystem := os.OSTypeForName(osname) + operatingSystem := ostype.OSTypeForName(osname) switch operatingSystem { - case os.Ubuntu: + case ostype.Ubuntu: cloudcfg.SetSystemUpdate(true) cloudcfg.AddScripts("set -xe", runCmd) // DisableNetworkManagement can still disable the bridge(s) creation. diff --git a/internal/provider/maas/userdata.go b/internal/provider/maas/userdata.go index 3573a09dcf65..f63895237361 100644 --- a/internal/provider/maas/userdata.go +++ b/internal/provider/maas/userdata.go @@ -8,16 +8,16 @@ import ( "github.com/juju/errors" "github.com/juju/utils/v4" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit" "github.com/juju/juju/internal/cloudconfig/providerinit/renderers" ) type MAASRenderer struct{} -func (MAASRenderer) Render(cfg cloudinit.CloudConfig, os jujuos.OSType) ([]byte, error) { +func (MAASRenderer) Render(cfg cloudinit.CloudConfig, os ostype.OSType) ([]byte, error) { switch os { - case jujuos.Ubuntu, jujuos.CentOS: + case ostype.Ubuntu, ostype.CentOS: return renderers.RenderYAML(cfg, utils.Gzip, renderers.ToBase64) default: return nil, errors.Errorf("Cannot encode userdata for OS: %s", os.String()) diff --git a/internal/provider/maas/userdata_test.go b/internal/provider/maas/userdata_test.go index 456cd603ac0e..eaa14830bd0d 100644 --- a/internal/provider/maas/userdata_test.go +++ b/internal/provider/maas/userdata_test.go @@ -11,7 +11,7 @@ import ( "github.com/juju/utils/v4" gc "gopkg.in/check.v1" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit/cloudinittest" "github.com/juju/juju/internal/provider/maas" "github.com/juju/juju/testing" @@ -27,12 +27,12 @@ func (s *RenderersSuite) TestMAASUnix(c *gc.C) { renderer := maas.MAASRenderer{} cloudcfg := &cloudinittest.CloudConfig{YAML: []byte("yaml")} - result, err := renderer.Render(cloudcfg, os.Ubuntu) + result, err := renderer.Render(cloudcfg, ostype.Ubuntu) c.Assert(err, jc.ErrorIsNil) expected := base64.StdEncoding.EncodeToString(utils.Gzip(cloudcfg.YAML)) c.Assert(string(result), jc.DeepEquals, expected) - result, err = renderer.Render(cloudcfg, os.CentOS) + result, err = renderer.Render(cloudcfg, ostype.CentOS) c.Assert(err, jc.ErrorIsNil) expected = base64.StdEncoding.EncodeToString(utils.Gzip(cloudcfg.YAML)) c.Assert(string(result), jc.DeepEquals, expected) @@ -41,7 +41,7 @@ func (s *RenderersSuite) TestMAASUnix(c *gc.C) { func (s *RenderersSuite) TestMAASUnknownOS(c *gc.C) { renderer := maas.MAASRenderer{} cloudcfg := &cloudinittest.CloudConfig{} - result, err := renderer.Render(cloudcfg, os.GenericLinux) + result, err := renderer.Render(cloudcfg, ostype.GenericLinux) c.Assert(result, gc.IsNil) c.Assert(err, gc.ErrorMatches, "Cannot encode userdata for OS: GenericLinux") } diff --git a/internal/provider/manual/environ.go b/internal/provider/manual/environ.go index 9a52c9968c39..26c0abd68a5b 100644 --- a/internal/provider/manual/environ.go +++ b/internal/provider/manual/environ.go @@ -55,10 +55,10 @@ type manualEnviron struct { user string mu sync.Mutex cfg *environConfig - // hw and series are detected by running a script on the + // hw and base are detected by running a script on the // target machine. We cache these, as they should not change. - hw *instance.HardwareCharacteristics - series string + hw *instance.HardwareCharacteristics + base corebase.Base } var errNoStartInstance = errors.New("manual provider cannot start instances") @@ -116,7 +116,7 @@ func (e *manualEnviron) Bootstrap(ctx environs.BootstrapContext, callCtx envcont if provisioned { return nil, manual.ErrProvisioned } - hw, series, err := e.seriesAndHardwareCharacteristics() + hw, base, err := e.baseAndHardwareCharacteristics() if err != nil { return nil, err } @@ -129,10 +129,6 @@ func (e *manualEnviron) Bootstrap(ctx environs.BootstrapContext, callCtx envcont return common.ConfigureMachine(ctx, ssh.DefaultClient, e.host, icfg, nil) } - base, err := corebase.GetBaseFromSeries(series) - if err != nil { - return nil, errors.Trace(err) - } result := &environs.BootstrapResult{ Arch: *hw.Arch, Base: base, @@ -346,7 +342,7 @@ func (e *manualEnviron) ConstraintsValidator(ctx envcontext.ProviderCallContext) } else { // We're running outside of the Juju controller, so we must // SSH to the machine and detect its architecture. - hw, _, err := e.seriesAndHardwareCharacteristics() + hw, _, err := e.baseAndHardwareCharacteristics() if err != nil { return nil, errors.Trace(err) } @@ -355,18 +351,18 @@ func (e *manualEnviron) ConstraintsValidator(ctx envcontext.ProviderCallContext) return validator, nil } -func (e *manualEnviron) seriesAndHardwareCharacteristics() (_ *instance.HardwareCharacteristics, series string, _ error) { +func (e *manualEnviron) baseAndHardwareCharacteristics() (*instance.HardwareCharacteristics, corebase.Base, error) { e.mu.Lock() defer e.mu.Unlock() if e.hw != nil { - return e.hw, e.series, nil + return e.hw, e.base, nil } - hw, series, err := sshprovisioner.DetectSeriesAndHardwareCharacteristics(e.host) + hw, base, err := sshprovisioner.DetectBaseAndHardwareCharacteristics(e.host) if err != nil { - return nil, "", errors.Trace(err) + return nil, corebase.Base{}, errors.Trace(err) } - e.hw, e.series = &hw, series - return e.hw, e.series, nil + e.hw, e.base = &hw, base + return e.hw, e.base, nil } func (*manualEnviron) Provider() environs.EnvironProvider { @@ -377,18 +373,18 @@ func isRunningController() bool { return filepath.Base(os.Args[0]) == names.Jujud } -// DetectSeries returns the series for the controller for this environment. +// DetectBase returns the base for the controller for this environment. // This method is part of the environs.HardwareCharacteristicsDetector interface. -func (e *manualEnviron) DetectSeries() (string, error) { - _, series, err := e.seriesAndHardwareCharacteristics() - return series, err +func (e *manualEnviron) DetectBase() (corebase.Base, error) { + _, base, err := e.baseAndHardwareCharacteristics() + return base, err } // DetectHardware returns the hardware characteristics for the controller for // this environment. This method is part of the environs.HardwareCharacteristicsDetector // interface. func (e *manualEnviron) DetectHardware() (*instance.HardwareCharacteristics, error) { - hw, _, err := e.seriesAndHardwareCharacteristics() + hw, _, err := e.baseAndHardwareCharacteristics() return hw, err } diff --git a/internal/provider/manual/environ_test.go b/internal/provider/manual/environ_test.go index e5c3994c7f52..80c5efd3e52f 100644 --- a/internal/provider/manual/environ_test.go +++ b/internal/provider/manual/environ_test.go @@ -13,6 +13,7 @@ import ( gc "gopkg.in/check.v1" "github.com/juju/juju/core/arch" + "github.com/juju/juju/core/base" "github.com/juju/juju/core/constraints" "github.com/juju/juju/core/instance" "github.com/juju/juju/environs" @@ -149,12 +150,12 @@ exit 0 } func (s *environSuite) TestConstraintsValidator(c *gc.C) { - s.PatchValue(&sshprovisioner.DetectSeriesAndHardwareCharacteristics, - func(string) (instance.HardwareCharacteristics, string, error) { + s.PatchValue(&sshprovisioner.DetectBaseAndHardwareCharacteristics, + func(string) (instance.HardwareCharacteristics, base.Base, error) { amd64 := "amd64" return instance.HardwareCharacteristics{ Arch: &amd64, - }, "", nil + }, base.Base{}, nil }, ) diff --git a/internal/provider/oci/environ.go b/internal/provider/oci/environ.go index c52b69fc2aa4..26cabca2b0bb 100644 --- a/internal/provider/oci/environ.go +++ b/internal/provider/oci/environ.go @@ -22,7 +22,7 @@ import ( "github.com/juju/juju/core/constraints" "github.com/juju/juju/core/instance" "github.com/juju/juju/core/network" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/environs" "github.com/juju/juju/environs/config" envcontext "github.com/juju/juju/environs/envcontext" @@ -437,13 +437,13 @@ func (e *Environ) getCloudInitConfig(osname string, apiPort int, statePort int) return cloudcfg, nil } - operatingSystem := os.OSTypeForName(osname) + operatingSystem := ostype.OSTypeForName(osname) switch operatingSystem { - case os.Ubuntu: + case ostype.Ubuntu: cloudcfg.AddRunCmd(fmt.Sprintf("/sbin/iptables -I INPUT -p tcp --dport %d -j ACCEPT", apiPort)) cloudcfg.AddRunCmd(fmt.Sprintf("/sbin/iptables -I INPUT -p tcp --dport %d -j ACCEPT", statePort)) cloudcfg.AddScripts("/etc/init.d/netfilter-persistent save") - case os.CentOS: + case ostype.CentOS: cloudcfg.AddRunCmd(fmt.Sprintf("firewall-cmd --zone=public --add-port=%d/tcp --permanent", apiPort)) cloudcfg.AddRunCmd(fmt.Sprintf("firewall-cmd --zone=public --add-port=%d/tcp --permanent", statePort)) cloudcfg.AddRunCmd("firewall-cmd --reload") diff --git a/internal/provider/oci/userdata.go b/internal/provider/oci/userdata.go index 8368208b9941..ccaff28d3173 100644 --- a/internal/provider/oci/userdata.go +++ b/internal/provider/oci/userdata.go @@ -8,7 +8,7 @@ import ( "github.com/juju/errors" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit" "github.com/juju/juju/internal/cloudconfig/providerinit/renderers" ) @@ -17,11 +17,11 @@ import ( type OCIRenderer struct{} // Renderer is defined in the renderers.ProviderRenderer interface -func (OCIRenderer) Render(cfg cloudinit.CloudConfig, os jujuos.OSType) ([]byte, error) { +func (OCIRenderer) Render(cfg cloudinit.CloudConfig, os ostype.OSType) ([]byte, error) { var renderedUdata []byte var err error switch os { - case jujuos.Ubuntu, jujuos.CentOS: + case ostype.Ubuntu, ostype.CentOS: renderedUdata, err = renderers.RenderYAML(cfg) default: return nil, errors.Errorf("Cannot encode userdata for OS: %s", os.String()) diff --git a/internal/provider/openstack/userdata.go b/internal/provider/openstack/userdata.go index 6d4ddbee3894..cddfc4ac5df4 100644 --- a/internal/provider/openstack/userdata.go +++ b/internal/provider/openstack/userdata.go @@ -8,16 +8,16 @@ import ( "github.com/juju/errors" "github.com/juju/utils/v4" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit" "github.com/juju/juju/internal/cloudconfig/providerinit/renderers" ) type OpenstackRenderer struct{} -func (OpenstackRenderer) Render(cfg cloudinit.CloudConfig, os jujuos.OSType) ([]byte, error) { +func (OpenstackRenderer) Render(cfg cloudinit.CloudConfig, os ostype.OSType) ([]byte, error) { switch os { - case jujuos.Ubuntu, jujuos.CentOS: + case ostype.Ubuntu, ostype.CentOS: return renderers.RenderYAML(cfg, utils.Gzip) default: return nil, errors.Errorf("Cannot encode userdata for OS: %s", os.String()) diff --git a/internal/provider/openstack/userdata_test.go b/internal/provider/openstack/userdata_test.go index a0ac52b8aa13..02de02307db4 100644 --- a/internal/provider/openstack/userdata_test.go +++ b/internal/provider/openstack/userdata_test.go @@ -9,7 +9,7 @@ import ( "github.com/juju/utils/v4" gc "gopkg.in/check.v1" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit/cloudinittest" "github.com/juju/juju/internal/provider/openstack" "github.com/juju/juju/testing" @@ -25,11 +25,11 @@ func (s *UserdataSuite) TestOpenstackUnix(c *gc.C) { renderer := openstack.OpenstackRenderer{} cloudcfg := &cloudinittest.CloudConfig{YAML: []byte("yaml")} - result, err := renderer.Render(cloudcfg, os.Ubuntu) + result, err := renderer.Render(cloudcfg, ostype.Ubuntu) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, utils.Gzip(cloudcfg.YAML)) - result, err = renderer.Render(cloudcfg, os.CentOS) + result, err = renderer.Render(cloudcfg, ostype.CentOS) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, utils.Gzip(cloudcfg.YAML)) } @@ -37,7 +37,7 @@ func (s *UserdataSuite) TestOpenstackUnix(c *gc.C) { func (s *UserdataSuite) TestOpenstackUnknownOS(c *gc.C) { renderer := openstack.OpenstackRenderer{} cloudcfg := &cloudinittest.CloudConfig{} - result, err := renderer.Render(cloudcfg, os.GenericLinux) + result, err := renderer.Render(cloudcfg, ostype.GenericLinux) c.Assert(result, gc.IsNil) c.Assert(err, gc.ErrorMatches, "Cannot encode userdata for OS: GenericLinux") } diff --git a/internal/provider/vsphere/environ_broker.go b/internal/provider/vsphere/environ_broker.go index 828642e84196..a199be5af602 100644 --- a/internal/provider/vsphere/environ_broker.go +++ b/internal/provider/vsphere/environ_broker.go @@ -16,7 +16,7 @@ import ( corebase "github.com/juju/juju/core/base" "github.com/juju/juju/core/instance" corenetwork "github.com/juju/juju/core/network" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/core/status" "github.com/juju/juju/environs" "github.com/juju/juju/environs/envcontext" @@ -123,7 +123,7 @@ func (env *sessionEnviron) newRawInstance( ) (_ *mo.VirtualMachine, _ *instance.HardwareCharacteristics, err error) { // Obtain the final constraints by merging with defaults. cons := args.Constraints - os := jujuos.OSTypeForName(args.InstanceConfig.Base.OS) + os := ostype.OSTypeForName(args.InstanceConfig.Base.OS) minRootDisk := common.MinRootDiskSizeGiB(os) * 1024 if cons.RootDisk == nil || *cons.RootDisk < minRootDisk { cons.RootDisk = &minRootDisk diff --git a/internal/provider/vsphere/environ_broker_test.go b/internal/provider/vsphere/environ_broker_test.go index dcf4b3af0e16..8af8f569905f 100644 --- a/internal/provider/vsphere/environ_broker_test.go +++ b/internal/provider/vsphere/environ_broker_test.go @@ -27,7 +27,7 @@ import ( corebase "github.com/juju/juju/core/base" "github.com/juju/juju/core/constraints" "github.com/juju/juju/core/instance" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/core/status" "github.com/juju/juju/environs" "github.com/juju/juju/environs/config" @@ -356,7 +356,7 @@ func (s *legacyEnvironBrokerSuite) TestStartInstanceDefaultConstraintsApplied(c var ( arch = "amd64" - rootDisk = common.MinRootDiskSizeGiB(os.Ubuntu) * 1024 + rootDisk = common.MinRootDiskSizeGiB(ostype.Ubuntu) * 1024 datastore = "datastore0" ) c.Assert(res.Hardware, jc.DeepEquals, &instance.HardwareCharacteristics{ @@ -410,7 +410,7 @@ func (s *legacyEnvironBrokerSuite) TestStartInstanceDefaultDiskSizeIsUsedForSmal startInstArgs.Constraints.RootDisk = &rootDisk res, err := s.env.StartInstance(s.callCtx, startInstArgs) c.Assert(err, jc.ErrorIsNil) - c.Assert(*res.Hardware.RootDisk, gc.Equals, common.MinRootDiskSizeGiB(os.Ubuntu)*uint64(1024)) + c.Assert(*res.Hardware.RootDisk, gc.Equals, common.MinRootDiskSizeGiB(ostype.Ubuntu)*uint64(1024)) } func (s *legacyEnvironBrokerSuite) TestStartInstanceSelectZone(c *gc.C) { @@ -619,7 +619,7 @@ func (s *legacyEnvironBrokerSuite) TestStartInstanceNoDatastoreSetting(c *gc.C) var ( arch = "amd64" - rootDisk = common.MinRootDiskSizeGiB(os.Ubuntu) * 1024 + rootDisk = common.MinRootDiskSizeGiB(ostype.Ubuntu) * 1024 rootDiskSource = "" ) diff --git a/internal/provider/vsphere/userdata.go b/internal/provider/vsphere/userdata.go index cec78353c7de..caad803938fa 100644 --- a/internal/provider/vsphere/userdata.go +++ b/internal/provider/vsphere/userdata.go @@ -7,16 +7,16 @@ package vsphere import ( "github.com/juju/errors" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit" "github.com/juju/juju/internal/cloudconfig/providerinit/renderers" ) type VsphereRenderer struct{} -func (VsphereRenderer) Render(cfg cloudinit.CloudConfig, os jujuos.OSType) ([]byte, error) { +func (VsphereRenderer) Render(cfg cloudinit.CloudConfig, os ostype.OSType) ([]byte, error) { switch os { - case jujuos.Ubuntu, jujuos.CentOS: + case ostype.Ubuntu, ostype.CentOS: return renderers.RenderYAML(cfg, renderers.ToBase64) default: return nil, errors.Errorf("Cannot encode userdata for OS: %s", os.String()) diff --git a/internal/provider/vsphere/userdata_test.go b/internal/provider/vsphere/userdata_test.go index 4c5c9da09eee..2962ef69f46a 100644 --- a/internal/provider/vsphere/userdata_test.go +++ b/internal/provider/vsphere/userdata_test.go @@ -10,7 +10,7 @@ import ( jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" - "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/cloudconfig/cloudinit/cloudinittest" "github.com/juju/juju/internal/provider/vsphere" "github.com/juju/juju/testing" @@ -26,12 +26,12 @@ func (s *UserdataSuite) TestVsphereUnix(c *gc.C) { renderer := vsphere.VsphereRenderer{} cloudcfg := &cloudinittest.CloudConfig{YAML: []byte("yaml")} - result, err := renderer.Render(cloudcfg, os.Ubuntu) + result, err := renderer.Render(cloudcfg, ostype.Ubuntu) c.Assert(err, jc.ErrorIsNil) expected := base64.StdEncoding.EncodeToString(cloudcfg.YAML) c.Assert(string(result), jc.DeepEquals, expected) - result, err = renderer.Render(cloudcfg, os.CentOS) + result, err = renderer.Render(cloudcfg, ostype.CentOS) c.Assert(err, jc.ErrorIsNil) expected = base64.StdEncoding.EncodeToString(cloudcfg.YAML) c.Assert(string(result), jc.DeepEquals, expected) @@ -40,7 +40,7 @@ func (s *UserdataSuite) TestVsphereUnix(c *gc.C) { func (s *UserdataSuite) TestVsphereUnknownOS(c *gc.C) { renderer := vsphere.VsphereRenderer{} cloudcfg := &cloudinittest.CloudConfig{} - result, err := renderer.Render(cloudcfg, os.GenericLinux) + result, err := renderer.Render(cloudcfg, ostype.GenericLinux) c.Assert(result, gc.IsNil) c.Assert(err, gc.ErrorMatches, "Cannot encode userdata for OS: GenericLinux") } diff --git a/internal/worker/caasupgrader/upgrader_test.go b/internal/worker/caasupgrader/upgrader_test.go index 32ef7ab22af8..0fb711085735 100644 --- a/internal/worker/caasupgrader/upgrader_test.go +++ b/internal/worker/caasupgrader/upgrader_test.go @@ -12,6 +12,7 @@ import ( "github.com/juju/juju/core/arch" coreos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/core/watcher/watchertest" "github.com/juju/juju/internal/worker/caasupgrader" "github.com/juju/juju/internal/worker/gate" @@ -47,7 +48,7 @@ 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(&coreos.HostOS, func() coreos.OSType { return coreos.Ubuntu }) + s.PatchValue(&coreos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) s.PatchValue(&jujuversion.Current, v.Number) } diff --git a/internal/worker/proxyupdater/proxyupdater.go b/internal/worker/proxyupdater/proxyupdater.go index 24182cca7683..5bfa38581f0f 100644 --- a/internal/worker/proxyupdater/proxyupdater.go +++ b/internal/worker/proxyupdater/proxyupdater.go @@ -11,7 +11,6 @@ import ( "strings" "github.com/juju/errors" - "github.com/juju/os/v2/series" "github.com/juju/packaging/v3/commands" "github.com/juju/packaging/v3/config" "github.com/juju/proxy" @@ -19,6 +18,7 @@ import ( "github.com/juju/juju/api/agent/proxyupdater" "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/core/snap" "github.com/juju/juju/core/watcher" ) @@ -164,16 +164,12 @@ func (w *proxyWorker) handleProxyValues(legacyProxySettings, jujuProxySettings p // getPackageCommander is a helper function which returns the // package commands implementation for the current system. -func getPackageCommander() (commands.PackageCommander, error) { - hostSeries, err := series.HostSeries() - if err != nil { - return nil, errors.Trace(err) - } - return commands.NewPackageCommander(hostSeries) +func getPackageCommander() commands.PackageCommander { + return commands.NewAptPackageCommander() } func (w *proxyWorker) handleSnapProxyValues(proxy proxy.Settings, storeID, storeAssertions, storeProxyURL string) { - if hostOS := getHostOS(); hostOS == os.CentOS { + if hostOS := getHostOS(); hostOS == ostype.CentOS { w.config.Logger.Tracef("no snap proxies on %s", hostOS) return } @@ -249,7 +245,7 @@ func (w *proxyWorker) handleSnapProxyValues(proxy proxy.Settings, storeID, store } func (w *proxyWorker) handleAptProxyValues(aptSettings proxy.Settings, aptMirror string) { - if hostOS := getHostOS(); hostOS == os.CentOS { + if hostOS := getHostOS(); hostOS == ostype.CentOS { w.config.Logger.Tracef("no apt proxies on %s", hostOS) return } @@ -261,11 +257,7 @@ func (w *proxyWorker) handleAptProxyValues(aptSettings proxy.Settings, aptMirror err error ) if updateNeeded { - paccmder, err = getPackageCommander() - if err != nil { - w.config.Logger.Errorf("unable to process apt proxy changes: %v", err) - return - } + paccmder = getPackageCommander() } if aptSettings != w.aptProxy || w.first { diff --git a/internal/worker/proxyupdater/proxyupdater_test.go b/internal/worker/proxyupdater/proxyupdater_test.go index 6aa4fda882fe..3fd2d188d6a2 100644 --- a/internal/worker/proxyupdater/proxyupdater_test.go +++ b/internal/worker/proxyupdater/proxyupdater_test.go @@ -226,8 +226,7 @@ func (s *ProxyUpdaterSuite) TestInitialStateLegacyProxy(c *gc.C) { s.waitForFile(c, s.proxyEnvFile, proxySettings.AsScriptEnvironment()) s.waitForFile(c, s.proxySystemdFile, proxySettings.AsSystemdDefaultEnv()) - paccmder, err := commands.NewPackageCommander(coretesting.HostSeries(c)) - c.Assert(err, jc.ErrorIsNil) + paccmder := commands.NewAptPackageCommander() s.waitForFile(c, pacconfig.AptProxyConfigFile, paccmder.ProxyConfigContents(aptProxySettings)+"\n") } @@ -249,8 +248,7 @@ func (s *ProxyUpdaterSuite) TestInitialStateJujuProxy(c *gc.C) { s.waitForFile(c, s.proxyEnvFile, empty.AsScriptEnvironment()) s.waitForFile(c, s.proxySystemdFile, empty.AsSystemdDefaultEnv()) - paccmder, err := commands.NewPackageCommander(coretesting.HostSeries(c)) - c.Assert(err, jc.ErrorIsNil) + paccmder := commands.NewAptPackageCommander() s.waitForFile(c, pacconfig.AptProxyConfigFile, paccmder.ProxyConfigContents(aptProxySettings)+"\n") } diff --git a/internal/worker/uniter/actions/resolver.go b/internal/worker/uniter/actions/resolver.go index d63417bbc699..7abb2976debd 100644 --- a/internal/worker/uniter/actions/resolver.go +++ b/internal/worker/uniter/actions/resolver.go @@ -61,7 +61,7 @@ func (r *actionsResolver) NextOp( // deferred until the unit is running. If the remote charm needs // updating, hold off on action running. if remoteState.ActionsBlocked || localState.OutdatedRemoteCharm { - r.logger.Infof("actions are blocked=%v; outdated remote charm=%v - have pending actions: %v", remoteState.ActionsBlocked, localState.OutdatedRemoteCharm, remoteState.ActionsPending) + r.logger.Debugf("actions are blocked=%v; outdated remote charm=%v - have pending actions: %v", remoteState.ActionsBlocked, localState.OutdatedRemoteCharm, remoteState.ActionsPending) if localState.ActionId == nil { r.logger.Debugf("actions are blocked, no in flight actions") return nil, resolver.ErrNoOperation diff --git a/internal/worker/uniter/paths_test.go b/internal/worker/uniter/paths_test.go index 4f93a96daf63..ba3d46e106a7 100644 --- a/internal/worker/uniter/paths_test.go +++ b/internal/worker/uniter/paths_test.go @@ -13,6 +13,7 @@ import ( gc "gopkg.in/check.v1" jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/worker/uniter" "github.com/juju/juju/juju/sockets" ) @@ -31,7 +32,7 @@ func relPathFunc(base string) func(parts ...string) string { } func (s *PathsSuite) TestOther(c *gc.C) { - s.PatchValue(&jujuos.HostOS, func() jujuos.OSType { return jujuos.Unknown }) + s.PatchValue(&jujuos.HostOS, func() ostype.OSType { return ostype.Unknown }) dataDir := c.MkDir() unitTag := names.NewUnitTag("some-application/323") @@ -102,7 +103,7 @@ func (s *PathsSuite) TestTCPRemote(c *gc.C) { } func (s *PathsSuite) TestWorkerPaths(c *gc.C) { - s.PatchValue(&jujuos.HostOS, func() jujuos.OSType { return jujuos.Unknown }) + s.PatchValue(&jujuos.HostOS, func() ostype.OSType { return ostype.Unknown }) dataDir := c.MkDir() unitTag := names.NewUnitTag("some-application/323") diff --git a/internal/worker/uniter/runner/context/env.go b/internal/worker/uniter/runner/context/env.go index 91974e69a8dc..c8caca2d55c8 100644 --- a/internal/worker/uniter/runner/context/env.go +++ b/internal/worker/uniter/runner/context/env.go @@ -7,9 +7,8 @@ import ( "fmt" "os" - "github.com/juju/os/v2/series" - jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" ) // Environmenter represent the os environ interface for fetching host level environment @@ -107,11 +106,11 @@ func ContextDependentEnvVars(env Environmenter) []string { // should be set for a hook context. func OSDependentEnvVars(paths Paths, env Environmenter) []string { switch jujuos.HostOS() { - case jujuos.Ubuntu: + case ostype.Ubuntu: return ubuntuEnv(paths, env) - case jujuos.CentOS: + case ostype.CentOS: return centosEnv(paths, env) - case jujuos.GenericLinux: + case ostype.GenericLinux: return genericLinuxEnv(paths, env) } return nil @@ -145,8 +144,8 @@ func centosEnv(paths Paths, envVars Environmenter) []string { // versions older than 7 are not supported and centos7 does not have patch 20150502 for ncurses 5.9 // with terminal definitions for "tmux" and "tmux-256color" - hostSeries, err := series.HostSeries() - if err == nil && hostSeries == "centos7" { + hostBase, err := jujuos.HostBase() + if err == nil && hostBase.Channel.Track == "7" { env = append(env, "TERM=screen-256color") } else { env = append(env, "TERM=tmux-256color") diff --git a/internal/worker/uniter/runner/context/env_test.go b/internal/worker/uniter/runner/context/env_test.go index c34a24c0e7b4..1361b49072ee 100644 --- a/internal/worker/uniter/runner/context/env_test.go +++ b/internal/worker/uniter/runner/context/env_test.go @@ -8,7 +8,6 @@ import ( "sort" "github.com/juju/names/v5" - osseries "github.com/juju/os/v2/series" "github.com/juju/proxy" jc "github.com/juju/testing/checkers" "github.com/juju/utils/v4/keyvalues" @@ -16,7 +15,9 @@ import ( "go.uber.org/mock/gomock" gc "gopkg.in/check.v1" + "github.com/juju/juju/core/base" jujuos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/core/secrets" "github.com/juju/juju/internal/worker/uniter/api" "github.com/juju/juju/internal/worker/uniter/runner/context" @@ -201,7 +202,7 @@ func (s *EnvSuite) TestEnvUbuntu(c *gc.C) { unit := api.NewMockUnit(ctrl) unit.EXPECT().Tag().Return(names.NewUnitTag("this-unit/123")).AnyTimes() - s.PatchValue(&jujuos.HostOS, func() jujuos.OSType { return jujuos.Ubuntu }) + s.PatchValue(&jujuos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) s.PatchValue(&jujuversion.Current, version.MustParse("1.2.3")) ubuntuVars := []string{ @@ -257,18 +258,18 @@ func (s *EnvSuite) TestEnvCentos(c *gc.C) { unit := api.NewMockUnit(ctrl) unit.EXPECT().Tag().Return(names.NewUnitTag("this-unit/123")).AnyTimes() - s.PatchValue(&jujuos.HostOS, func() jujuos.OSType { return jujuos.CentOS }) + s.PatchValue(&jujuos.HostOS, func() ostype.OSType { return ostype.CentOS }) s.PatchValue(&jujuversion.Current, version.MustParse("1.2.3")) // TERM is different for centos7. - for _, testSeries := range []string{"centos7", "centos8"} { - s.PatchValue(&osseries.HostSeries, func() (string, error) { return testSeries, nil }) + for _, testBase := range []base.Base{base.MustParseBaseFromString("centos@7"), base.MustParseBaseFromString("centos@8")} { + s.PatchValue(&jujuos.HostBase, func() (base.Base, error) { return testBase, nil }) centosVars := []string{ "LANG=C.UTF-8", "PATH=path-to-tools:foo:bar", } - if testSeries == "centos7" { + if testBase.Channel.Track == "7" { centosVars = append(centosVars, "TERM=screen-256color") } else { centosVars = append(centosVars, "TERM=tmux-256color") @@ -318,7 +319,7 @@ func (s *EnvSuite) TestEnvGenericLinux(c *gc.C) { unit := api.NewMockUnit(ctrl) unit.EXPECT().Tag().Return(names.NewUnitTag("this-unit/123")).AnyTimes() - s.PatchValue(&jujuos.HostOS, func() jujuos.OSType { return jujuos.GenericLinux }) + s.PatchValue(&jujuos.HostOS, func() ostype.OSType { return ostype.GenericLinux }) s.PatchValue(&jujuversion.Current, version.MustParse("1.2.3")) genericLinuxVars := []string{ @@ -370,7 +371,7 @@ func (s *EnvSuite) TestHostEnv(c *gc.C) { unit := api.NewMockUnit(ctrl) unit.EXPECT().Tag().Return(names.NewUnitTag("this-unit/123")).AnyTimes() - s.PatchValue(&jujuos.HostOS, func() jujuos.OSType { return jujuos.GenericLinux }) + s.PatchValue(&jujuos.HostOS, func() ostype.OSType { return ostype.GenericLinux }) s.PatchValue(&jujuversion.Current, version.MustParse("1.2.3")) genericLinuxVars := []string{ diff --git a/internal/worker/upgrader/upgrader_test.go b/internal/worker/upgrader/upgrader_test.go index 313bca813bf4..c8df7a5501bf 100644 --- a/internal/worker/upgrader/upgrader_test.go +++ b/internal/worker/upgrader/upgrader_test.go @@ -26,7 +26,6 @@ import ( agenterrors "github.com/juju/juju/agent/errors" agenttools "github.com/juju/juju/agent/tools" "github.com/juju/juju/core/arch" - coreos "github.com/juju/juju/core/os" "github.com/juju/juju/core/watcher/watchertest" "github.com/juju/juju/environs/filestorage" "github.com/juju/juju/environs/storage" @@ -81,7 +80,6 @@ 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(&coreos.HostOS, func() coreos.OSType { return coreos.Ubuntu }) s.PatchValue(&jujuversion.Current, v.Number) } diff --git a/internal/worker/upgradeseries/export_test.go b/internal/worker/upgradeseries/export_test.go index a5d7eff26e9d..2bd9a4e2abad 100644 --- a/internal/worker/upgradeseries/export_test.go +++ b/internal/worker/upgradeseries/export_test.go @@ -3,10 +3,12 @@ package upgradeseries +import "github.com/juju/juju/core/base" + type patcher interface { PatchValue(interface{}, interface{}) } -func PatchHostSeries(patcher patcher, series string) { - patcher.PatchValue(&hostSeries, func() (string, error) { return series, nil }) +func PatchHostBase(patcher patcher, b base.Base) { + patcher.PatchValue(&hostBase, func() (base.Base, error) { return b, nil }) } diff --git a/internal/worker/upgradeseries/manifold.go b/internal/worker/upgradeseries/manifold.go index cdedb9ff5424..687fc199c613 100644 --- a/internal/worker/upgradeseries/manifold.go +++ b/internal/worker/upgradeseries/manifold.go @@ -67,8 +67,8 @@ func (config ManifoldConfig) newWorker(_ context.Context, a agent.Agent, apiCall // Partially apply the upgrader factory function so we only need to request // using the getter for the to/from OS series. - newUpgrader := func(currentSeries, targetSeries string) (Upgrader, error) { - return NewUpgrader(currentSeries, targetSeries, service.NewServiceManagerWithDefaults(), config.Logger) + newUpgrader := func() (Upgrader, error) { + return NewUpgrader(service.NewServiceManagerWithDefaults(), config.Logger) } cfg := Config{ diff --git a/internal/worker/upgradeseries/mocks/package_mock.go b/internal/worker/upgradeseries/mocks/package_mock.go index dd14f271e767..eaecdbee5e76 100644 --- a/internal/worker/upgradeseries/mocks/package_mock.go +++ b/internal/worker/upgradeseries/mocks/package_mock.go @@ -12,6 +12,7 @@ package mocks import ( reflect "reflect" + base "github.com/juju/juju/core/base" model "github.com/juju/juju/core/model" watcher "github.com/juju/juju/core/watcher" names "github.com/juju/names/v5" @@ -41,23 +42,8 @@ func (m *MockFacade) EXPECT() *MockFacadeMockRecorder { return m.recorder } -// CurrentSeries mocks base method. -func (m *MockFacade) CurrentSeries() (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CurrentSeries") - ret0, _ := ret[0].(string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CurrentSeries indicates an expected call of CurrentSeries. -func (mr *MockFacadeMockRecorder) CurrentSeries() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentSeries", reflect.TypeOf((*MockFacade)(nil).CurrentSeries)) -} - // FinishUpgradeSeries mocks base method. -func (m *MockFacade) FinishUpgradeSeries(arg0 string) error { +func (m *MockFacade) FinishUpgradeSeries(arg0 base.Base) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "FinishUpgradeSeries", arg0) ret0, _ := ret[0].(error) @@ -142,21 +128,6 @@ func (mr *MockFacadeMockRecorder) StartUnitCompletion(arg0 any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartUnitCompletion", reflect.TypeOf((*MockFacade)(nil).StartUnitCompletion), arg0) } -// TargetSeries mocks base method. -func (m *MockFacade) TargetSeries() (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TargetSeries") - ret0, _ := ret[0].(string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// TargetSeries indicates an expected call of TargetSeries. -func (mr *MockFacadeMockRecorder) TargetSeries() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TargetSeries", reflect.TypeOf((*MockFacade)(nil).TargetSeries)) -} - // UnitsCompleted mocks base method. func (m *MockFacade) UnitsCompleted() ([]names.UnitTag, error) { m.ctrl.T.Helper() diff --git a/internal/worker/upgradeseries/shim.go b/internal/worker/upgradeseries/shim.go index 877ba87aea9b..5dafcb7e83e6 100644 --- a/internal/worker/upgradeseries/shim.go +++ b/internal/worker/upgradeseries/shim.go @@ -8,6 +8,7 @@ import ( "github.com/juju/juju/api/agent/upgradeseries" "github.com/juju/juju/api/base" + corebase "github.com/juju/juju/core/base" "github.com/juju/juju/core/model" "github.com/juju/juju/core/watcher" ) @@ -19,13 +20,11 @@ type Facade interface { MachineStatus() (model.UpgradeSeriesStatus, error) UnitsPrepared() ([]names.UnitTag, error) UnitsCompleted() ([]names.UnitTag, error) - CurrentSeries() (string, error) - TargetSeries() (string, error) // Setters StartUnitCompletion(reason string) error SetMachineStatus(status model.UpgradeSeriesStatus, reason string) error - FinishUpgradeSeries(string) error + FinishUpgradeSeries(corebase.Base) error PinMachineApplications() (map[string]error, error) UnpinMachineApplications() (map[string]error, error) SetInstanceStatus(model.UpgradeSeriesStatus, string) error diff --git a/internal/worker/upgradeseries/upgrader.go b/internal/worker/upgradeseries/upgrader.go index 6fddcc0fc730..eef2a44524fc 100644 --- a/internal/worker/upgradeseries/upgrader.go +++ b/internal/worker/upgradeseries/upgrader.go @@ -25,16 +25,6 @@ type Upgrader interface { type upgrader struct { logger Logger - // jujuCurrentSeries is what Juju thinks the - // current series of the machine is. - jujuCurrentSeries string - - // fromSeries is the actual current series, - // determined directly from the machine. - fromSeries string - - toSeries string - machineAgent string unitAgents []string @@ -44,18 +34,11 @@ type upgrader struct { // NewUpgrader uses the input function to determine the series that should be // supported, and returns a reference to a new Upgrader that supports it. func NewUpgrader( - currentSeries, toSeries string, manager service.SystemdServiceManager, logger Logger, + manager service.SystemdServiceManager, logger Logger, ) (Upgrader, error) { - fromSeries, err := hostSeries() - if err != nil { - return nil, errors.Trace(err) - } return &upgrader{ - logger: logger, - jujuCurrentSeries: currentSeries, - fromSeries: fromSeries, - toSeries: toSeries, - manager: manager, + logger: logger, + manager: manager, }, nil } diff --git a/internal/worker/upgradeseries/upgrader_test.go b/internal/worker/upgradeseries/upgrader_test.go index 7cb412c81579..fd5c9f992a85 100644 --- a/internal/worker/upgradeseries/upgrader_test.go +++ b/internal/worker/upgradeseries/upgrader_test.go @@ -37,7 +37,7 @@ func (s *upgraderSuite) TestPerformUpgrade(c *gc.C) { defer ctrl.Finish() s.setupMocks(ctrl) - upg := s.newUpgrader(c, "focal", "jammy") + upg := s.newUpgrader(c) c.Assert(upg.PerformUpgrade(), jc.ErrorIsNil) } @@ -49,8 +49,8 @@ func (s *upgraderSuite) setupMocks(ctrl *gomock.Controller) { s.manager.EXPECT().FindAgents(paths.NixDataDir).Return(s.machineService, []string{"jujud-unit-ubuntu-0", "jujud-unit-redis-0"}, nil, nil) } -func (s *upgraderSuite) newUpgrader(c *gc.C, currentSeries, toSeries string) upgradeseries.Upgrader { - upg, err := upgradeseries.NewUpgrader(currentSeries, toSeries, s.manager, s.logger) +func (s *upgraderSuite) newUpgrader(c *gc.C) upgradeseries.Upgrader { + upg, err := upgradeseries.NewUpgrader(s.manager, s.logger) c.Assert(err, jc.ErrorIsNil) return upg } diff --git a/internal/worker/upgradeseries/worker.go b/internal/worker/upgradeseries/worker.go index b19bbbcbd84a..239cd0450d3d 100644 --- a/internal/worker/upgradeseries/worker.go +++ b/internal/worker/upgradeseries/worker.go @@ -9,17 +9,17 @@ import ( "github.com/juju/errors" "github.com/juju/names/v5" - "github.com/juju/os/v2/series" "github.com/juju/worker/v4" "github.com/juju/worker/v4/catacomb" "github.com/juju/juju/core/model" + "github.com/juju/juju/core/os" "github.com/juju/juju/rpc/params" ) //go:generate go run go.uber.org/mock/mockgen -package mocks -destination mocks/package_mock.go github.com/juju/juju/internal/worker/upgradeseries Facade,UnitDiscovery,Upgrader -var hostSeries = series.HostSeries +var hostBase = os.HostBase // Logger represents the methods required to emit log messages. type Logger interface { @@ -50,7 +50,7 @@ type Config struct { // UpgraderFactory is a factory method that will return an upgrader capable // of handling service and agent binary manipulation for a // runtime-determined current and target OS series. - UpgraderFactory func(string, string) (Upgrader, error) + UpgraderFactory func() (Upgrader, error) } // Validate validates the upgrade-series worker configuration. @@ -83,7 +83,7 @@ type upgradeSeriesWorker struct { catacomb catacomb.Catacomb logger Logger unitDiscovery UnitDiscovery - upgraderFactory func(string, string) (Upgrader, error) + upgraderFactory func() (Upgrader, error) // Some local state retained for reporting purposes. mu sync.Mutex @@ -248,17 +248,7 @@ func (w *upgradeSeriesWorker) transitionPrepareComplete() error { } w.logger.Infof("preparing service units for series upgrade") - currentSeries, err := w.CurrentSeries() - if err != nil { - return errors.Trace(err) - } - - toSeries, err := w.TargetSeries() - if err != nil { - return errors.Trace(err) - } - - upgrader, err := w.upgraderFactory(currentSeries, toSeries) + upgrader, err := w.upgraderFactory() if err != nil { return errors.Trace(err) } @@ -318,11 +308,11 @@ func (w *upgradeSeriesWorker) handleCompleted() error { return errors.Trace(err) } - s, err := hostSeries() + b, err := hostBase() if err != nil { return errors.Trace(err) } - if err = w.FinishUpgradeSeries(s); err != nil { + if err = w.FinishUpgradeSeries(b); err != nil { return errors.Trace(err) } if err = w.unpinLeaders(); err != nil { diff --git a/internal/worker/upgradeseries/worker_test.go b/internal/worker/upgradeseries/worker_test.go index 7b4ae5ef5b7a..9985af8e9000 100644 --- a/internal/worker/upgradeseries/worker_test.go +++ b/internal/worker/upgradeseries/worker_test.go @@ -15,6 +15,7 @@ import ( "go.uber.org/mock/gomock" gc "gopkg.in/check.v1" + "github.com/juju/juju/core/base" "github.com/juju/juju/core/model" "github.com/juju/juju/core/watcher" workermocks "github.com/juju/juju/internal/worker/mocks" @@ -178,8 +179,6 @@ func (s *workerSuite) expectMachinePrepareStartedUnitFilesWrittenProgressPrepare exp.MachineStatus().Return(model.UpgradeSeriesPrepareStarted, nil) s.expectSetInstanceStatus(model.UpgradeSeriesPrepareStarted, "preparing units") s.expectUnitsPrepared("wordpress/0", "mysql/0") - exp.CurrentSeries().Return("focal", nil) - exp.TargetSeries().Return("jammy", nil) s.upgrader.EXPECT().PerformUpgrade().Return(nil) s.expectSetInstanceStatus(model.UpgradeSeriesPrepareStarted, "completing preparation") @@ -285,12 +284,13 @@ func (s *workerSuite) TestMachineCompletedFinishUpgradeSeries(c *gc.C) { } func (s *workerSuite) expectMachineCompletedFinishUpgradeSeries() { - s.patchHost("xenial") + b := base.MustParseBaseFromString("ubuntu@16.04") + s.patchHost(b) exp := s.facade.EXPECT() exp.MachineStatus().Return(model.UpgradeSeriesCompleted, nil) s.expectSetInstanceStatus(model.UpgradeSeriesCompleted, "finalising upgrade") - exp.FinishUpgradeSeries("xenial").Return(nil) + exp.FinishUpgradeSeries(b).Return(nil) s.expectSetInstanceStatus(model.UpgradeSeriesCompleted, "success") exp.UnpinMachineApplications().Return(map[string]error{ @@ -318,7 +318,7 @@ func (s *workerSuite) newWorker(c *gc.C) worker.Worker { Logger: s.logger, Facade: s.facade, UnitDiscovery: s.unitDiscovery, - UpgraderFactory: func(_, _ string) (upgradeseries.Upgrader, error) { return s.upgrader, nil }, + UpgraderFactory: func() (upgradeseries.Upgrader, error) { return s.upgrader, nil }, } w, err := upgradeseries.NewWorker(cfg) @@ -363,8 +363,8 @@ func (s *workerSuite) cleanKill(c *gc.C, w worker.Worker) { workertest.CleanKill(c, w) } -func (s *workerSuite) patchHost(series string) { - upgradeseries.PatchHostSeries(s, series) +func (s *workerSuite) patchHost(b base.Base) { + upgradeseries.PatchHostBase(s, b) } // notify returns a suite behaviour that will cause the upgrade-series watcher diff --git a/state/application.go b/state/application.go index 803d0efa93a7..3112453d5dc6 100644 --- a/state/application.go +++ b/state/application.go @@ -3218,13 +3218,13 @@ func (a *Application) ApplicationConfig() (config.ConfigAttributes, error) { cfg, err := readSettings(a.st.db(), settingsC, a.applicationConfigKey()) if err != nil { if errors.Is(err, errors.NotFound) { - return config.ConfigAttributes(nil), nil + return config.ConfigAttributes{}, nil } return nil, errors.Annotatef(err, "application config for application %q", a.doc.Name) } if len(cfg.Keys()) == 0 { - return config.ConfigAttributes(nil), nil + return config.ConfigAttributes{}, nil } return cfg.Map(), nil } diff --git a/state/application_test.go b/state/application_test.go index cc5033cee4dd..3faf7afa6cce 100644 --- a/state/application_test.go +++ b/state/application_test.go @@ -4457,6 +4457,7 @@ var updateApplicationConfigTests = []struct { }, { about: "unset missing string", update: config.ConfigAttributes{"outlook": nil}, + expect: config.ConfigAttributes{}, }, { about: `empty strings are valid`, initial: config.ConfigAttributes{"outlook": "positive"}, @@ -4480,6 +4481,7 @@ var updateApplicationConfigTests = []struct { about: "unset non-string type", initial: config.ConfigAttributes{"skill-level": 303}, update: config.ConfigAttributes{"skill-level": nil}, + expect: config.ConfigAttributes{}, }} func (s *ApplicationSuite) TestUpdateApplicationConfig(c *gc.C) { @@ -4523,7 +4525,7 @@ func (s *ApplicationSuite) TestApplicationConfigNotFoundNoError(c *gc.C) { cfg, err := app.ApplicationConfig() c.Assert(err, jc.ErrorIsNil) - c.Check(cfg, gc.IsNil) + c.Assert(cfg, gc.HasLen, 0) } func (s *ApplicationSuite) TestStatusInitial(c *gc.C) { diff --git a/state/state_test.go b/state/state_test.go index 53c2f03cda17..515574dd3cc3 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -40,6 +40,7 @@ import ( "github.com/juju/juju/core/model" "github.com/juju/juju/core/network" coreos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/core/permission" "github.com/juju/juju/core/status" "github.com/juju/juju/core/upgrade" @@ -4045,7 +4046,7 @@ func (s *StateSuite) TestSetModelAgentVersionOnOtherModel(c *gc.C) { current := version.MustParseBinary("1.24.7-ubuntu-amd64") s.PatchValue(&jujuversion.Current, current.Number) s.PatchValue(&arch.HostArch, func() string { return current.Arch }) - s.PatchValue(&coreos.HostOS, func() coreos.OSType { return coreos.Ubuntu }) + s.PatchValue(&coreos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) otherSt := s.Factory.MakeModel(c, nil) defer otherSt.Close() diff --git a/state/stateenvirons/package_test.go b/state/stateenvirons/package_test.go index 742e77251d4f..58d8c3b65018 100644 --- a/state/stateenvirons/package_test.go +++ b/state/stateenvirons/package_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" coretesting "github.com/juju/juju/testing" ) @@ -14,7 +15,7 @@ func TestPackage(t *testing.T) { // At this stage, Juju only supports running the apiservers and database // on Ubuntu. If we end up officially supporting CentOS, then we should // make sure we run the tests there. - if os.HostOS() != os.Ubuntu { + if os.HostOS() != ostype.Ubuntu { t.Skipf("skipping tests on %v", os.HostOS()) } coretesting.MgoTestPackage(t) diff --git a/testing/base.go b/testing/base.go index 99f067db5527..ffbab40c0820 100644 --- a/testing/base.go +++ b/testing/base.go @@ -24,6 +24,7 @@ import ( "github.com/juju/juju/core/arch" "github.com/juju/juju/core/base" coreos "github.com/juju/juju/core/os" + "github.com/juju/juju/core/os/ostype" "github.com/juju/juju/internal/wrench" "github.com/juju/juju/juju/osenv" jujuversion "github.com/juju/juju/version" @@ -104,14 +105,14 @@ func SkipIfWindowsBug(c *gc.C, bugID string) { // SkipUnlessControllerOS skips the test if the current OS is not a supported // controller OS. func SkipUnlessControllerOS(c *gc.C) { - if coreos.HostOS() != coreos.Ubuntu { + if coreos.HostOS() != ostype.Ubuntu { c.Skip("Test disabled for non-controller OS") } } // SkipLXDNotSupported will skip tests if the host does not support LXD func SkipLXDNotSupported(c *gc.C) { - if coreos.HostOS() != coreos.Ubuntu { + if coreos.HostOS() != ostype.Ubuntu { c.Skip("Test disabled for non-LXD OS") } } @@ -276,16 +277,8 @@ func CurrentVersion() version.Binary { } // HostSeries returns series.HostSeries(), asserting on error. -func HostSeries(c *gc.C) string { - hostSeries, err := series.HostSeries() - c.Assert(err, jc.ErrorIsNil) - return hostSeries -} - func HostBase(c *gc.C) base.Base { - hostSeries, err := series.HostSeries() - c.Assert(err, jc.ErrorIsNil) - base, err := base.GetBaseFromSeries(hostSeries) + hostBase, err := coreos.HostBase() c.Assert(err, jc.ErrorIsNil) - return base + return hostBase } diff --git a/version/current_test.go b/version/current_test.go index e6e6817b4878..54d21c6a6bed 100644 --- a/version/current_test.go +++ b/version/current_test.go @@ -6,11 +6,10 @@ package version import ( "os/exec" - osseries "github.com/juju/os/v2/series" + jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" - corebase "github.com/juju/juju/core/base" - "github.com/juju/juju/core/os" + coreos "github.com/juju/juju/core/os" ) type CurrentSuite struct{} @@ -18,22 +17,12 @@ type CurrentSuite struct{} var _ = gc.Suite(&CurrentSuite{}) func (*CurrentSuite) TestCurrentSeries(c *gc.C) { - s, err := osseries.HostSeries() - if err != nil || s == "unknown" { - s = "n/a" - } - out, err := exec.Command("lsb_release", "-c").CombinedOutput() - + b, err := coreos.HostBase() if err != nil { - // If the command fails (for instance if we're running on some other - // platform) then CurrentSeries should be unknown. - currentOS, err := corebase.GetOSFromSeries(s) - c.Assert(err, gc.IsNil) - // There is no lsb_release command on CentOS. - if s != "n/a" && currentOS == os.CentOS { - c.Check(s, gc.Matches, `centos\d+`) - } - } else { - c.Assert(string(out), gc.Equals, "Codename:\t"+s+"\n") + c.Fatal(err) } + out, err := exec.Command("lsb_release", "-r").CombinedOutput() + + c.Assert(err, jc.ErrorIsNil) + c.Assert(string(out), gc.Equals, "Release:\t"+b.Channel.Track+"\n") }