Skip to content

Commit

Permalink
Merge pull request juju#9966 from hmlanigan/watchapplxdprofile
Browse files Browse the repository at this point in the history
juju#9966

## Description of change

Add a watcher to model cache to notify when the lxd profiles applied to a machine may need to change. 

## QA steps

1. `export JUJU_DEV_FEATURE_FLAGS=instance-mutater`
2. `bootstrap lxd with --config logging-config='<root>=DEBUG;unit=DEBUG;juju.core.cache=TRACE;juju.worker.instancemuter=TRACE'`
2. `juju debug-log -m controller --replay --include-module juju.worker.instancemutater --include-module juju.core.cache`
3. download the ubuntu charm to a local directory (~/charms)
4. `juju deploy ~/charms/ubunu`
3. the worker should log that a notify was recieved.
3. `juju upgrade-charm ubuntu --path ~/charms/ubuntu`
3. the worker should not log that a notify was recieved.
4. `juju deploy ./testcharms/charm-repo/quantal/lxd-profile`
3. the worker should log that a notify was recieved.
4. `juju upgrade-charm lxd-profile --path ./testcharms/charm-repo/quantal/lxd-profile`
3. the worker should log that a notification was received.
3. `juju add-unit ubuntu --to 1`
4. the worker should not log that no notification should be received for machine 1.
3. `juju add-unit lxd-profile --to 0`
3. the worker should not log that notification should be received for machine 0.
  • Loading branch information
jujubot authored Apr 1, 2019
2 parents 35e3ead + aa6c7f5 commit b34b230
Show file tree
Hide file tree
Showing 19 changed files with 730 additions and 126 deletions.
5 changes: 4 additions & 1 deletion apiserver/facades/agent/instancemutater/instancemutater.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,10 @@ func (api *InstanceMutaterAPI) watchOneEntityApplication(canAccess common.AuthFu
if err != nil {
return result, err
}
watch := machine.WatchApplicationLXDProfiles()
watch, err := machine.WatchApplicationLXDProfiles()
if err != nil {
return result, err
}
// Consume the initial event before sending the result.
if _, ok := <-watch.Changes(); ok {
result.NotifyWatcherId = api.resources.Register(watch)
Expand Down
29 changes: 27 additions & 2 deletions apiserver/facades/agent/instancemutater/instancemutater_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,26 @@ func (s *InstanceMutaterAPIWatchApplicationLXDProfilesSuite) TestWatchApplicatio
})
}

func (s *InstanceMutaterAPIWatchApplicationLXDProfilesSuite) TestWatchApplicationLXDProfilesModelCacheError(c *gc.C) {
defer s.setup(c).Finish()

facade := s.facadeAPIForScenario(c,
s.expectAuthMachineAgent,
s.expectLife(s.machineTag),
s.expectWatchApplicationLXDProfilesError,
)

result, err := facade.WatchApplicationLXDProfiles(params.Entities{
Entities: []params.Entity{{Tag: s.machineTag.String()}},
})
c.Assert(err, gc.IsNil)
c.Assert(result, gc.DeepEquals, params.NotifyWatchResults{
Results: []params.NotifyWatchResult{{
Error: common.ServerError(errors.New("error from model cache")),
}},
})
}

func (s *InstanceMutaterAPIWatchApplicationLXDProfilesSuite) expectAuthController() {
s.authorizer.EXPECT().AuthController().Return(true)
}
Expand All @@ -920,7 +940,7 @@ func (s *InstanceMutaterAPIWatchApplicationLXDProfilesSuite) expectWatchApplicat
}()

s.model.EXPECT().Machine(s.machineTag.Id()).Return(s.machine, nil)
s.machine.EXPECT().WatchApplicationLXDProfiles().Return(s.watcher)
s.machine.EXPECT().WatchApplicationLXDProfiles().Return(s.watcher, nil)
s.watcher.EXPECT().Changes().Return(ch)
s.resources.EXPECT().Register(s.watcher).Return("1")
}
Expand All @@ -931,6 +951,11 @@ func (s *InstanceMutaterAPIWatchApplicationLXDProfilesSuite) expectWatchApplicat
close(ch)

s.model.EXPECT().Machine(s.machineTag.Id()).Return(s.machine, nil)
s.machine.EXPECT().WatchApplicationLXDProfiles().Return(s.watcher)
s.machine.EXPECT().WatchApplicationLXDProfiles().Return(s.watcher, nil)
s.watcher.EXPECT().Changes().Return(ch)
}

func (s *InstanceMutaterAPIWatchApplicationLXDProfilesSuite) expectWatchApplicationLXDProfilesError() {
s.model.EXPECT().Machine(s.machineTag.Id()).Return(s.machine, nil)
s.machine.EXPECT().WatchApplicationLXDProfiles().Return(s.watcher, errors.New("error from model cache"))
}
2 changes: 1 addition & 1 deletion apiserver/facades/agent/instancemutater/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,5 @@ type ModelCache interface {

// ModelCacheMachine represents a point of use Machine from the cache package.
type ModelCacheMachine interface {
WatchApplicationLXDProfiles() cache.NotifyWatcher
WatchApplicationLXDProfiles() (cache.NotifyWatcher, error)
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apiserver/facades/agent/instancemutater/shim.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,6 @@ type modelCacheMachine struct {
*cache.Machine
}

func (m *modelCacheMachine) WatchApplicationLXDProfiles() cache.NotifyWatcher {
func (m *modelCacheMachine) WatchApplicationLXDProfiles() (cache.NotifyWatcher, error) {
return m.Machine.WatchApplicationLXDProfiles()
}
18 changes: 18 additions & 0 deletions core/cache/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import (
)

const (
// the application's charm url has changed.
applicationCharmURLChange = "application-charmurl-change"
// application config has changed.
applicationConfigChange = "application-config-change"
)

Expand Down Expand Up @@ -55,9 +58,20 @@ func (a *Application) WatchConfig(keys ...string) *ConfigWatcher {
return newConfigWatcher(keys, a.hashCache, a.hub, a.topic(applicationConfigChange))
}

// appCharmUrlChange contains an appName and it's charm URL. To be used
// when publishing for applicationCharmURLChange.
type appCharmUrlChange struct {
appName string
chURL string
}

func (a *Application) setDetails(details ApplicationChange) {
a.mu.Lock()

if a.details.CharmURL != details.CharmURL {
a.hub.Publish(a.modelTopic(applicationCharmURLChange), appCharmUrlChange{appName: a.details.Name, chURL: details.CharmURL})
}

a.details = details
hashCache, configHash := newHashCache(
details.Config, a.metrics.ApplicationHashCacheHit, a.metrics.ApplicationHashCacheMiss)
Expand All @@ -77,3 +91,7 @@ func (a *Application) setDetails(details ApplicationChange) {
func (a *Application) topic(suffix string) string {
return a.details.ModelUUID + ":" + a.details.Name + ":" + suffix
}

func (a *Application) modelTopic(suffix string) string {
return modelTopic(a.details.ModelUUID, suffix)
}
2 changes: 1 addition & 1 deletion core/cache/application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ var appChange = cache.ApplicationChange{
ModelUUID: "model-uuid",
Name: "application-name",
Exposed: false,
CharmURL: "www.charm-url.com",
CharmURL: "www.charm-url.com-1",
Life: life.Alive,
MinUnits: 0,
Constraints: constraints.Value{},
Expand Down
6 changes: 5 additions & 1 deletion core/cache/charm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
gc "gopkg.in/check.v1"

"github.com/juju/juju/core/cache"
"github.com/juju/juju/core/lxdprofile"
)

type CharmSuite struct {
Expand All @@ -21,5 +22,8 @@ func (s *CharmSuite) SetUpTest(c *gc.C) {

var charmChange = cache.CharmChange{
ModelUUID: "model-uuid",
CharmURL: "www.charm-url.com",
CharmURL: "www.charm-url.com-1",
LXDProfile: lxdprofile.Profile{
Config: map[string]string{"key": "value"},
},
}
20 changes: 17 additions & 3 deletions core/cache/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@ package cache

var (
CreateControllerGauges = createControllerGauges
NewModel = newModel
NewApplication = newApplication
NewModel = newModel
)

// Expose SetDetails for testing.

func (a *Application) SetDetails(details ApplicationChange) {
a.setDetails(details)
}

func (m *Model) SetDetails(details ModelChange) {
m.setDetails(details)
}

func (a *Application) SetDetails(details ApplicationChange) {
a.setDetails(details)
// Expose Remove* for testing

func (m *Model) RemoveUnit(ch RemoveUnit) {
m.removeUnit(ch)
}

// Expose Update* for testing.
Expand All @@ -28,3 +34,11 @@ func (m *Model) UpdateMachine(details MachineChange) {
func (m *Model) UpdateUnit(details UnitChange) {
m.updateUnit(details)
}

func (m *Model) UpdateApplication(details ApplicationChange) {
m.updateApplication(details)
}

func (m *Model) UpdateCharm(details CharmChange) {
m.updateCharm(details)
}
Loading

0 comments on commit b34b230

Please sign in to comment.