-
Notifications
You must be signed in to change notification settings - Fork 491
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11846 from howbazaar/2.8-watch-models-application…
…-status #11846 If an application status hasn't been explicitly set by a unit its status is derived from the units themselves. This derivation code was moved into the model cache, but the all watcher translation later itself was overlooked. This branch uses the cached controller information to determine the application status if it is Unset, like the status code does. There were no tests around the all watcher code on the apiserver side, so added some to test the conversion behaviour. ## QA steps ```sh juju bootstrap lxd test juju deploy ~jameinel/ubuntu-lite ubuntu juju db # using juju-db plugin to get mongo prompt db.statuses.find().pretty() # check for _id: <uuid>:a#ubuntu # "status" : "unset", # run pylibjuju example to look at the watcher tox -e example -- examples/allwatcher.py # will see a line like: ['application', 'change', {'model-uuid': '11252a44-d946-4305-8292-a650cfa4b138', 'name': 'ubuntu', 'exposed': False, 'charm-url': 'cs:~jameinel/ubuntu-lite-7', 'owner-tag': '', 'life': 'alive', 'min-units': 0, 'constraints': {}, 'subordinate': False, 'status': {'current': 'waiting', 'message': 'waiting for machine', 'since': '2020-07-21T05:42:48.050629314Z', 'version': ''}, 'workload-version': ''}] # confirm that status isn't 'unset' ```
- Loading branch information
Showing
2 changed files
with
156 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// Copyright 2020 Canonical Ltd. | ||
// Licensed under the AGPLv3, see LICENCE file for details. | ||
|
||
package apiserver | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/juju/worker/v2/workertest" | ||
gc "gopkg.in/check.v1" | ||
|
||
"github.com/juju/juju/apiserver/params" | ||
"github.com/juju/juju/core/cache" | ||
"github.com/juju/juju/core/life" | ||
"github.com/juju/juju/core/multiwatcher" | ||
"github.com/juju/juju/core/status" | ||
"github.com/juju/juju/testing" | ||
jc "github.com/juju/testing/checkers" | ||
) | ||
|
||
type allWatcherSuite struct { | ||
testing.BaseSuite | ||
} | ||
|
||
var _ = gc.Suite(&allWatcherSuite{}) | ||
|
||
func (s *allWatcherSuite) watcher() *SrvAllWatcher { | ||
// We explicitly don't have a real watcher here as the tests | ||
// are for the translation of types. | ||
return &SrvAllWatcher{} | ||
} | ||
|
||
func (s *allWatcherSuite) TestTranslateApplicationWithStatus(c *gc.C) { | ||
w := s.watcher() | ||
input := &multiwatcher.ApplicationInfo{ | ||
ModelUUID: testing.ModelTag.Id(), | ||
Name: "test-app", | ||
CharmURL: "test-app", | ||
Life: life.Alive, | ||
Status: multiwatcher.StatusInfo{ | ||
Current: status.Active, | ||
}, | ||
} | ||
output := w.translateApplication(input) | ||
c.Assert(output, jc.DeepEquals, ¶ms.ApplicationInfo{ | ||
ModelUUID: input.ModelUUID, | ||
Name: input.Name, | ||
CharmURL: input.CharmURL, | ||
Life: input.Life, | ||
Status: params.StatusInfo{ | ||
Current: status.Active, | ||
}, | ||
}) | ||
} | ||
|
||
func (s *allWatcherSuite) setupCache(c *gc.C) *cache.Controller { | ||
changes := make(chan interface{}) | ||
handled := make(chan interface{}) | ||
notify := func(evt interface{}) { | ||
c.Logf("%#v", evt) | ||
select { | ||
case handled <- evt: | ||
case <-time.After(testing.LongWait): | ||
c.Fatalf("handled notify not retrieved") | ||
} | ||
} | ||
sendEvent := func(event interface{}) { | ||
select { | ||
case changes <- event: | ||
case <-time.After(testing.LongWait): | ||
c.Fatal("cache did not accept event") | ||
} | ||
select { | ||
case <-handled: | ||
case <-time.After(testing.LongWait): | ||
c.Fatal("cache did not handle event") | ||
} | ||
} | ||
|
||
controller, err := cache.NewController(cache.ControllerConfig{ | ||
Changes: changes, | ||
Notify: notify, | ||
}) | ||
c.Assert(err, jc.ErrorIsNil) | ||
s.AddCleanup(func(c *gc.C) { workertest.CleanKill(c, controller) }) | ||
|
||
sendEvent(cache.ModelChange{ | ||
ModelUUID: testing.ModelTag.Id(), | ||
// Defaults for everything else. | ||
}) | ||
sendEvent(cache.ApplicationChange{ | ||
ModelUUID: testing.ModelTag.Id(), | ||
Name: "test-app", | ||
Status: status.StatusInfo{ | ||
Status: status.Unset, | ||
}, | ||
// Defaults for everything else. | ||
}) | ||
sendEvent(cache.UnitChange{ | ||
ModelUUID: testing.ModelTag.Id(), | ||
Name: "test-app/0", | ||
Application: "test-app", | ||
WorkloadStatus: status.StatusInfo{ | ||
Status: status.Active, | ||
}, | ||
// Defaults for everything else. | ||
}) | ||
|
||
return controller | ||
} | ||
|
||
func (s *allWatcherSuite) TestTranslateApplicationStatusUnset(c *gc.C) { | ||
controller := s.setupCache(c) | ||
w := s.watcher() | ||
w.controller = controller | ||
input := &multiwatcher.ApplicationInfo{ | ||
ModelUUID: testing.ModelTag.Id(), | ||
Name: "test-app", | ||
CharmURL: "test-app", | ||
Life: life.Alive, | ||
Status: multiwatcher.StatusInfo{ | ||
Current: status.Unset, | ||
}, | ||
} | ||
output := w.translateApplication(input) | ||
c.Assert(output, jc.DeepEquals, ¶ms.ApplicationInfo{ | ||
ModelUUID: input.ModelUUID, | ||
Name: input.Name, | ||
CharmURL: input.CharmURL, | ||
Life: input.Life, | ||
Status: params.StatusInfo{ | ||
Current: status.Active, | ||
}, | ||
}) | ||
} |