New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Trigger upgrade-series-prepare hook. #8864
Changes from 28 commits
1c0e8c7
0ac2132
02ce53c
be3d968
c5f67d3
678e376
3d71446
9873531
025d928
095e39e
132b877
9e06d5e
e7d842a
afd2b0e
ce7f0c9
418f215
737461e
d31fefe
cd35901
93b5a64
92d223c
f7e1ab8
1ac1597
facc529
ff4ac60
2eda0a1
7ca5aae
27b7ec7
cef8aed
aa6dcff
e5c98bb
c622313
0d31aea
71f3958
44050d1
600d130
8cee315
fb9f7cd
550ecd7
3d830be
b99b95a
2ab106c
6c00b4e
a5c59a6
8cc0cae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -642,6 +642,76 @@ func (u *Unit) WatchActionNotifications() (watcher.StringsWatcher, error) { | |
return w, nil | ||
} | ||
|
||
// WatchActionNotifications returns a StringsWatcher for observing the state of | ||
// a series upgrade. | ||
func (u *Unit) WatchUpgradeSeriesNotifications() (watcher.NotifyWatcher, error) { | ||
var results params.NotifyWatchResults | ||
args := params.Entities{ | ||
Entities: []params.Entity{{Tag: u.tag.String()}}, | ||
} | ||
err := u.st.facade.FacadeCall("WatchUpgradeSeriesNotifications", args, &results) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if len(results.Results) != 1 { | ||
return nil, errors.Errorf("expected 1 result, got %d", len(results.Results)) | ||
} | ||
result := results.Results[0] | ||
if result.Error != nil { | ||
return nil, result.Error | ||
} | ||
w := apiwatcher.NewNotifyWatcher(u.st.facade.RawAPICaller(), result) | ||
return w, nil | ||
} | ||
|
||
// UpgradeSeriesStatus returns the upgrade series status of a unit from remote state | ||
func (u *Unit) UpgradeSeriesStatus() (params.UnitSeriesUpgradeStatus, error) { | ||
var results params.UpgradeSeriesStatusResults | ||
args := params.Entities{ | ||
Entities: []params.Entity{{Tag: u.tag.String()}}, | ||
} | ||
err := u.st.facade.FacadeCall("UpgradeSeriesStatus", args, &results) | ||
if err != nil { | ||
return "", err | ||
} | ||
if len(results.Results) != 1 { | ||
return "", errors.Errorf("expected 1 result, got %d", len(results.Results)) | ||
} | ||
result := results.Results[0] | ||
if result.Error != nil { | ||
//TODO (externalreality) The code to do convert api errors (with | ||
//error codes) back to normal Go errors is in bad spot and | ||
//causes import cycles which is why we don't use it here and may | ||
//be the reason why it has few uses despite being useful. | ||
if params.IsCodeNotFound(result.Error) { | ||
return "", errors.NewNotFound(result.Error, "") | ||
} | ||
return "", result.Error | ||
} | ||
return result.Status, nil | ||
} | ||
|
||
// UpgradeSeriesStatus sets the upgrade series status of the unit in the remote state | ||
func (u *Unit) SetUpgradeSeriesStatus(status params.UnitSeriesUpgradeStatus) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same params comment as line 668 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. Both the args and return values from API calls should not expose the params package. |
||
var results params.ErrorResults | ||
args := params.SetUpgradeSeriesStatusParams{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The idea of the bulk calls isn't to apply a particular value to multiple targets, but instead to be able to process multiple actions in a single call. I think this is why the param struct this way feels weird. The bulk nature of the SetUpgradeSeriesStatus should be to take pairs of agents and status values. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will do |
||
Entities: []params.Entity{{Tag: u.tag.String()}}, | ||
Status: status, | ||
} | ||
err := u.st.facade.FacadeCall("SetUpgradeSeriesStatus", args, &results) | ||
if err != nil { | ||
return err | ||
} | ||
if len(results.Results) != 1 { | ||
return errors.Errorf("expected 1 result, got %d", len(results.Results)) | ||
} | ||
result := results.Results[0] | ||
if result.Error != nil { | ||
return result.Error | ||
} | ||
return nil | ||
} | ||
|
||
// RequestReboot sets the reboot flag for its machine agent | ||
func (u *Unit) RequestReboot() error { | ||
machineId, err := u.AssignedMachine() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -684,6 +684,86 @@ func (s *unitSuite) TestWatchActionNotificationsMoreResults(c *gc.C) { | |
c.Assert(err.Error(), gc.Equals, "expected 1 result, got 2") | ||
} | ||
|
||
func (s *unitSuite) TestWatchUpgradeSeriesNotifications(c *gc.C) { | ||
watcher, err := s.apiUnit.WatchUpgradeSeriesNotifications() | ||
c.Assert(err, jc.ErrorIsNil) | ||
|
||
notifyWatcher := watchertest.NewNotifyWatcherC(c, watcher, s.BackingState.StartSync) | ||
defer notifyWatcher.AssertStops() | ||
|
||
// Why do I have two initial events?!? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are apparently two initial events coming out of this puppy. Why? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you find out why this is happening? I noticed the TestWatchActionNotificationsMoreResults() is testing that only 1 watch notification happens. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that is what I mean above. No I don't know why, its innocuous (since the Uniter will just loop twice), but I don't know why its sending two initial events. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Histerical raisins. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All watchers send an initial event to trigger the checking of initial state. Many times this isn't useful, and you'll see comments like "consume initial event". There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, fixed now. |
||
_, ok := <-notifyWatcher.Watcher.Changes() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a bare channel operation is almost always dangerous, as it can block indefinitely (and then you only find out when the test suite is killed after 25min). However, getting 2 events is even worse, as it throws off everyone's expectations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Excellent! Yes, the other watchers do consume an initial event on the server side - subsequently, on the client side, the additional event is not observed. Thank you @jameinel. |
||
notifyWatcher.Assert(ok, jc.IsTrue) | ||
|
||
notifyWatcher.AssertOneChange() | ||
|
||
s.CreateUpgradeSeriesLock(c) | ||
|
||
// Expect a notification that the document was created (i.e. a lock was placed) | ||
notifyWatcher.AssertOneChange() | ||
|
||
err = s.wordpressMachine.RemoveUpgradeSeriesLock() | ||
c.Assert(err, jc.ErrorIsNil) | ||
|
||
// A notification that the document was removed (i.e. the lock was released) | ||
notifyWatcher.AssertOneChange() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. other than the initial double event, this test looks good. |
||
} | ||
|
||
func (s *unitSuite) TestUpgradeSeriesStatus(c *gc.C) { | ||
// First we create the prepare lock | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it worth checking the pre-condition of s.apiUnit.UpgradeSeriesStatus() before we create the lock? So that we see the value changes to Started? It seems odd that you have this test, which says the status is Started, even though there isn't a call to SetUpgradeSeriesStatus(UnitStarted). If we want to just have "started" as the initial state, then I'd say we don't need a test that you can set the state to Started (drop TestSetUpgradeSeriesStatus, or change it to set the status to Completed) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It just so happens that the remote state starts in the Uniter: UnitNotStarted There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, but correct, lets test our assumption! We will put in a check of the pre-condition. I only note it in a comment. |
||
s.CreateUpgradeSeriesLock(c) | ||
|
||
// Then we check to see the status of our upgrade. We note that creating | ||
// the lock essentially kicks off an upgrade for the perspective of | ||
// assigned units. | ||
status, err := s.apiUnit.UpgradeSeriesStatus() | ||
c.Assert(err, jc.ErrorIsNil) | ||
c.Assert(status, gc.Equals, params.UnitStarted) | ||
} | ||
|
||
func (s *unitSuite) TestSetUpgradeSeriesStatus(c *gc.C) { | ||
// First we create the prepare lock or the required state will not exists | ||
s.CreateUpgradeSeriesLock(c) | ||
|
||
err := s.apiUnit.SetUpgradeSeriesStatus(params.UnitStarted) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps use UnitCompleted instead, as UnitStarted is now the "default" |
||
c.Assert(err, jc.ErrorIsNil) | ||
|
||
// Check to see that the upgrade status has been set appropriately | ||
status, err := s.apiUnit.UpgradeSeriesStatus() | ||
c.Assert(err, jc.ErrorIsNil) | ||
c.Assert(status, gc.Equals, params.UnitStarted) | ||
} | ||
|
||
func (s *unitSuite) TestSetUpgradeSeriesStatusShouldOnlySetSpecifiedUnit(c *gc.C) { | ||
// add another unit | ||
unit2, err := s.wordpressApplication.AddUnit(state.AddUnitParams{}) | ||
c.Assert(err, jc.ErrorIsNil) | ||
|
||
err = unit2.AssignToMachine(s.wordpressMachine) | ||
c.Assert(err, jc.ErrorIsNil) | ||
|
||
// Creating a lock for the machine transitions all units to started state | ||
s.CreateUpgradeSeriesLock(c, unit2.Name()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I realize that this syntax is correct, as it is a locally defined function that knows about the various machines/units in play, and only creates a lock for s.wordpressMachine and takes additional unit names to include. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does this invocation also pass in a unit name? It isn't clear to me. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its because the Suite function takes a list of "additional units to include in the preparation" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It compares the passed in values with the known values, and thus if someone has added a machine then we can't start the update. The user must confirm again in light of the new information, that is, a newly created machine. Its just used for validation. |
||
|
||
// Complete one unit | ||
err = unit2.SetUpgradeSeriesStatus(params.UnitCompleted) | ||
c.Assert(err, jc.ErrorIsNil) | ||
|
||
// The other unit should still be in the started state | ||
status, err := s.wordpressUnit.UpgradeSeriesStatus() | ||
c.Assert(err, jc.ErrorIsNil) | ||
c.Assert(status, gc.Equals, params.UnitStarted) | ||
} | ||
|
||
func (s *unitSuite) CreateUpgradeSeriesLock(c *gc.C, additionalUnits ...string) { | ||
unitNames := additionalUnits | ||
unitNames = append(unitNames, s.wordpressUnit.Name()) | ||
series := "trust" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: trusty There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we going to add validation that the series mentioned is one that juju knows about? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is validation at the CLI level. Will add validation at the DB level too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would probably make sense to do the validation at the API server level rather than the DB level. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we do validate the series via an api call, before calling prepare, as the machine lock is created... perhaps it can be validated again when creating the machine lock document? |
||
|
||
err := s.wordpressMachine.CreateUpgradeSeriesLock(unitNames, series) | ||
c.Assert(err, jc.ErrorIsNil) | ||
} | ||
|
||
func (s *unitSuite) TestApplicationNameAndTag(c *gc.C) { | ||
c.Assert(s.apiUnit.ApplicationName(), gc.Equals, s.wordpressApplication.Name()) | ||
c.Assert(s.apiUnit.ApplicationTag(), gc.Equals, s.wordpressApplication.Tag()) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -984,6 +984,111 @@ func (u *UniterAPI) WatchActionNotifications(args params.Entities) (params.Strin | |
return common.WatchActionNotifications(args, canAccess, watchOne), nil | ||
} | ||
|
||
// WatchActionNotifications returns a StringsWatcher for observing the status of an Upgrade Series | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. doc string: WatchActionNotifications creates a NotifyWatcher There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bah, the copy pasta monster - or creepy pasta - depending on which way you want to look at it. |
||
func (u *UniterAPI) WatchUpgradeSeriesNotifications(args params.Entities) (params.NotifyWatchResults, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm wondering if we can put these into an api shared between the uniter and the new upgrade series worker? Both need to WatchUpgradeSeriesNotifications(), UpgradeSeriesStatus() etc. Entities deal in tags, so we can get different data if necessary for machines and units. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code is being moved into a new API as per the above, therefor there is no reason to bump version here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ExternalReality I'm not sure what you are meaning "as per the above". If we are adding methods to the uniter API, then we need to bump the facade version, even if they are brought in through a common implementation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @howbazaar, the above comment by @hmlanigan. The code is being moved out of the UniterAPI entirely in the next PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally we have a facade per-worker, and while they might both embed a common.Methods, they would be separate grouping of methods. |
||
result := params.NotifyWatchResults{ | ||
Results: make([]params.NotifyWatchResult, len(args.Entities)), | ||
} | ||
canAccess, err := u.accessUnit() | ||
if err != nil { | ||
return params.NotifyWatchResults{}, err | ||
} | ||
for i, entity := range args.Entities { | ||
tag, err := names.ParseUnitTag(entity.Tag) | ||
if err != nil { | ||
result.Results[i].Error = common.ServerError(common.ErrPerm) | ||
continue | ||
} | ||
watcherId := "" | ||
if !canAccess(tag) { | ||
result.Results[i].Error = common.ServerError(common.ErrPerm) | ||
continue | ||
} | ||
unit, err := u.getUnit(tag) | ||
if err != nil { | ||
result.Results[i].Error = common.ServerError(err) | ||
continue | ||
} | ||
w, err := unit.WatchUpgradeSeriesNotifications() | ||
if err != nil { | ||
result.Results[i].Error = common.ServerError(err) | ||
continue | ||
} | ||
watcherId = u.resources.Register(w) | ||
result.Results[i].NotifyWatcherId = watcherId | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per your earlier question of "why do I have 2 events": There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (put another way, the call to Watch() should return the watcher identity, and the content of the first Next() result, and then on the client side, those should be split up into the appropriate responses. A NotifyWatcher doesn't have any actual content to return just an event that gets consumed on the server and regenerated on the client) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jameinel I'm unclear on what if anything should be added to the code here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You want to consume the first Next() event here, and "transmit" the value along with the return of Watch() which the transmit is a no-op for us. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hey @howbazaar, I swallowed the extra event on the server side, here I was swallowing both the servers initial event and the clients initial event on the client. My fault. |
||
} | ||
return result, nil | ||
} | ||
|
||
func (u *UniterAPI) UpgradeSeriesStatus(args params.Entities) (params.UpgradeSeriesStatusResults, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doc comment needed. |
||
result := params.UpgradeSeriesStatusResults{ | ||
Results: make([]params.UpgradeSeriesStatusResult, len(args.Entities)), | ||
} | ||
canAccess, err := u.accessUnit() | ||
if err != nil { | ||
return params.UpgradeSeriesStatusResults{}, err | ||
} | ||
for i, entity := range args.Entities { | ||
tag, err := names.ParseUnitTag(entity.Tag) | ||
if err != nil { | ||
result.Results[i].Error = common.ServerError(common.ErrPerm) | ||
continue | ||
} | ||
|
||
if !canAccess(tag) { | ||
result.Results[i].Error = common.ServerError(common.ErrPerm) | ||
continue | ||
} | ||
unit, err := u.getUnit(tag) | ||
if err != nil { | ||
result.Results[i].Error = common.ServerError(err) | ||
continue | ||
} | ||
status, err := unit.UpgradeSeriesStatus() | ||
if err != nil { | ||
result.Results[i].Error = common.ServerError(err) | ||
continue | ||
} | ||
result.Results[i].Status = status | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
func (u *UniterAPI) SetUpgradeSeriesStatus(args params.SetUpgradeSeriesStatusParams) (params.UpgradeSeriesStatusResults, error) { | ||
result := params.UpgradeSeriesStatusResults{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest using params.ErrorsResults, the status string isn't returned with Set. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agreed. |
||
Results: make([]params.UpgradeSeriesStatusResult, len(args.Entities)), | ||
} | ||
canAccess, err := u.accessUnit() | ||
if err != nil { | ||
return params.UpgradeSeriesStatusResults{}, err | ||
} | ||
for i, entity := range args.Entities { | ||
//TODO[externalreality] refactor all of this, its being copied often. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. certainly it can be shared by all methods on this type. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could probably refactor the next three if statements into something like: getUnitOrServerError(tag names.Tag) (*state.Unit, *params.Error) |
||
tag, err := names.ParseUnitTag(entity.Tag) | ||
if err != nil { | ||
result.Results[i].Error = common.ServerError(common.ErrPerm) | ||
continue | ||
} | ||
if !canAccess(tag) { | ||
result.Results[i].Error = common.ServerError(common.ErrPerm) | ||
continue | ||
} | ||
unit, err := u.getUnit(tag) | ||
if err != nil { | ||
result.Results[i].Error = common.ServerError(err) | ||
continue | ||
} | ||
err = unit.SetUpgradeSeriesStatus(args.Status) | ||
if err != nil { | ||
result.Results[i].Error = common.ServerError(err) | ||
continue | ||
} | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
// ConfigSettings returns the complete set of application charm config | ||
// settings available to each given unit. | ||
func (u *UniterAPI) ConfigSettings(args params.Entities) (params.ConfigSettingsResults, error) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1276,3 +1276,17 @@ type DumpModelRequest struct { | |
Entities []Entity `json:"entities"` | ||
Simplified bool `json:"simplified"` | ||
} | ||
|
||
type UpgradeSeriesStatusResult struct { | ||
Error *Error `json:"error,omitempty"` | ||
Status UnitSeriesUpgradeStatus `json:"status,omitempty"` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Coming in late, but what is the rationale for having a particular type here rather thatn just a string? Since this is only wire protocol, different types give us no benefit. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also a bit weird returning the status in a set result call. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed, we just pass around base string now. With validations to convert it into a typed const. |
||
} | ||
|
||
type UpgradeSeriesStatusResults struct { | ||
Results []UpgradeSeriesStatusResult `json:"results,omitempty"` | ||
} | ||
|
||
type SetUpgradeSeriesStatusParams struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why assume that every entity will receive the same status? Suggest type SetUpgradeSeriesStatusArg struct There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're probably not going to need that flexibility There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking it follows the pattern of current params structs and will could be useful for the juju piece results. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that we probably don't need that flexibility, but the pattern generally used is to have arrays of structs where the embedded struct would have entity and status. In reality, we are really only going to be calling this with a single entity from the uniter anyway. |
||
Entities []Entity `json:"entities"` | ||
Status UnitSeriesUpgradeStatus `json:"status"` | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright 2018 Canonical Ltd. | ||
// Licensed under the AGPLv3, see LICENCE file for details. | ||
|
||
package params | ||
|
||
//MachineSeriesUpgradeStatus is the current status a machine series upgrade | ||
type MachineSeriesUpgradeStatus string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps these constants would be better suited in core/model package? |
||
|
||
const ( | ||
MachineSeriesUpgradeNotStarted MachineSeriesUpgradeStatus = "NotStarted" | ||
MachineSeriesUpgradeStarted MachineSeriesUpgradeStatus = "Started" | ||
MachineSeriesUpgradeUnitsRunning MachineSeriesUpgradeStatus = "UnitsRunning" | ||
MachineSeriesUpgradeJujuComplete MachineSeriesUpgradeStatus = "JujuComplete" | ||
MachineSeriesUpgradeAgentsStopped MachineSeriesUpgradeStatus = "AgentsStopped" | ||
MachineSeriesUpgradeComplete MachineSeriesUpgradeStatus = "Complete" | ||
) | ||
|
||
//UnitSeriesUpgradeStatus is the current status of an upgrade | ||
type UnitSeriesUpgradeStatus string | ||
|
||
const ( | ||
UnitNotStarted UnitSeriesUpgradeStatus = "NotStarted" | ||
UnitStarted UnitSeriesUpgradeStatus = "Started" | ||
UnitErrored UnitSeriesUpgradeStatus = "Errored" | ||
UnitCompleted UnitSeriesUpgradeStatus = "Completed" | ||
) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -121,7 +121,7 @@ var debugHooksTests = []struct { | |
}, { | ||
info: `invalid hook`, | ||
args: []string{"mysql/0", "invalid-hook"}, | ||
error: `unit "mysql/0" contains neither hook nor action "invalid-hook", valid actions are [fakeaction] and valid hooks are [collect-metrics config-changed install juju-info-relation-broken juju-info-relation-changed juju-info-relation-departed juju-info-relation-joined leader-deposed leader-elected leader-settings-changed meter-status-changed server-admin-relation-broken server-admin-relation-changed server-admin-relation-departed server-admin-relation-joined server-relation-broken server-relation-changed server-relation-departed server-relation-joined start stop update-status upgrade-charm]`, | ||
error: `unit "mysql/0" contains neither hook nor action "invalid-hook", valid actions are [fakeaction] and valid hooks are [collect-metrics config-changed install juju-info-relation-broken juju-info-relation-changed juju-info-relation-departed juju-info-relation-joined leader-deposed leader-elected leader-settings-changed meter-status-changed post-series-upgrade pre-series-upgrade server-admin-relation-broken server-admin-relation-changed server-admin-relation-departed server-admin-relation-joined server-relation-broken server-relation-changed server-relation-departed server-relation-joined start stop update-status upgrade-charm]`, | ||
}, { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This list is getting long enough, I have to question if it is being useful vs having something you can run to find out the list... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about just a regex There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. its more a signal that we're not giving a helpful message to the user if we're drowning them in a list that wraps multiple times. |
||
info: `no args at all`, | ||
args: nil, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be a string instead? params structs shouldn't be returned from an API call. does that extend to consts in params?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are just string constants. We should probably move them out of params.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's do that now, since they're added in this pr. :-) perhaps @jameinel knows a good spot?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't return any params structs or types from the API package.
If they really need their own type, I'd be tempted to make a core package. Alternatively keep the type in the same api package as the method.