-
Notifications
You must be signed in to change notification settings - Fork 529
feat(dqlite): model status service layer #18393
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
Conversation
65f0ed0
to
a0d1a46
Compare
Hey @ycliuhw, Cheers for the PR. Are we able to move this implementation into the model service (https://github.com/juju/juju/blob/main/domain/model/service/modelservice.go) ? |
ed99cde
to
d9547a2
Compare
d9547a2
to
2ec3f7f
Compare
0650424
to
62a5c35
Compare
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.
Cheers @ycliuhw, Ignore any comments I have made that you are already on top of. I will get cracking on the state layer.
domain/model/service/modelservice.go
Outdated
return s.modelSt.Delete(ctx, s.modelID) | ||
} | ||
|
||
// Status returns the status of the model. |
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.
this should include the word "current" I think. For example "Status returns the current status of the model".
We should also document the possible error returns that could result from this function.
For example model not found is a likely scenario even if small.
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.
The state does not exist yet. We could probably assume the state should return a not found error at least.
if modelState.Destroying { | ||
return model.StatusInfo{ | ||
Status: corestatus.Destroying, | ||
Message: "the model is being destroyed", |
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 don't seem to be setting the time field on any off these computed status values.
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.
No, because we don't know the time of the status change.
If you can figure out where we can find it, feel free to include the time in the result returned from the state.
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'll need to ensure the timestamp for the underlying source is modelled. Until then, the caller can interpret zero time as "unknown". We should make sure to update things like juju status
to avoid printing junk.
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.
Are you sure that is what we want to do? Should we just not set time.Now()
at least that has meaning over time.Zero()
.
If we tell the client to start doing is == time.Zero it means we have changed the contract of the api and we should technically bump the apiserver facade version.
Keep it simple I say.
4779d10
to
b54f522
Compare
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.
looking good. Just a couple of small things.
b54f522
to
89bc0b8
Compare
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 need to remove "busy" as a status that can be set
@@ -8,8 +8,7 @@ INSERT INTO model_status_value VALUES | |||
(0, 'error'), | |||
(1, 'available'), | |||
-- We set the model status to busy when the model is being upgraded. | |||
(2, 'busy'), | |||
(3, 'suspended'); | |||
(2, 'busy'); |
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 are going to derive this from whether a model is migrating, right?
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 still use busy for upgrade
.
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.
Can we please change timestamp to time.Time
rather than a pointer. I originally gave a +1 to make progress but we should make this change before landing.
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.
Until timestamp is modelled, we'll need to ensure things like juju status
do not print junk when the timestamp is zero.
if modelState.Destroying { | ||
return model.StatusInfo{ | ||
Status: corestatus.Destroying, | ||
Message: "the model is being destroyed", |
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'll need to ensure the timestamp for the underlying source is modelled. Until then, the caller can interpret zero time as "unknown". We should make sure to update things like juju status
to avoid printing junk.
5b3ea7d
to
9ace4ef
Compare
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.
Ta @ycliuhw, just a few quick comments.
if modelState.Destroying { | ||
return model.StatusInfo{ | ||
Status: corestatus.Destroying, | ||
Message: "the model is being destroyed", |
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.
Are you sure that is what we want to do? Should we just not set time.Now()
at least that has meaning over time.Zero()
.
If we tell the client to start doing is == time.Zero it means we have changed the contract of the api and we should technically bump the apiserver facade version.
Keep it simple I say.
9ace4ef
to
5d26091
Compare
/merge |
#18437 This PR introduces several clean up tasks to the model state around moving over to internal errors and also better defining some of the types we use on the database. The main goal of this PR is to introduce a new state method for fetching a model's "state". That is the various state various parts of the model are in at any given time so that a model status can be derived from data. It has been decided to implement model status in this way instead of a specific table in the database to track the status of a model. With this approach we are able to calculate the status of model at a given time and not have the complex logic needed to control status setting for a model from several places in the code base. This PR was done in conjunction with #18393 ## Checklist - [x] Code style: imports ordered, good names, simple structure, etc - [x] Comments saying why design decisions were made - [x] Go unit tests, with comments saying what you're testing - ~[ ] [Integration tests](https://github.com/juju/juju/tree/main/tests), with comments saying what you're testing~ - ~[ ] [doc.go](https://discourse.charmhub.io/t/readme-in-packages/451) added or updated in changed packages~ ## QA steps Unit tests are enough for now. ## Documentation changes N/A ## Links **Jira card:** JUJU-7100
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.
@tlm, @ycliuhw Can we do a follow up to this one please?
// ModelState is the model state required by this service. This is the model
// database state, not the controller state.
type ModelState interface {
// Create creates a new model with all of its associated metadata.
Create(context.Context, model.ReadOnlyModelCreationArgs) error
// Delete deletes a model.
Delete(context.Context, coremodel.UUID) error
// Model returns the read only model information set in the database.
Model(context.Context) (coremodel.ReadOnlyModel, error)
}
// ControllerState is the controller state required by this service. This is the
// controller database, not the model state.
type ControllerState interface {
// GetModel returns the model with the given UUID.
GetModel(context.Context, coremodel.UUID) (coremodel.Model, error)
// GetModelState returns the model state for the given model.
// It returns [modelerrors.NotFound] if the model does not exist for the given UUID.
GetModelState(context.Context, coremodel.UUID) (model.ModelState, error)
}
This is semantically clunky. We have 2 things with the same name, but with entirely different meanings, used within a paragraph of code. I suggest ModelStatus
.
GetStatus
is returning a derived StatusInfo
, but we will need access to the non-derived status via the service. Can we:
- Change
GetStatus
toGetStatusInfo
. - Implement a
GetStatus
that returns theModelState
(proposed asModelStatus
above). - Include
Importing
in the struct above and thev_model_state
view.
This PR introduces the a new service method in the
model
domain package for the model status feature:destroying
if the model is being destroyed;suspended
if the model has an invalid cloud credential;busy
if the model is being migrated;available
;Drive-by:
Checklist
Integration tests, with comments saying what you're testingdoc.go added or updated in changed packagesQA steps
unit tests.
Documentation changes
No
Links
Jira card: JUJU-7099