Skip to content

Commit

Permalink
Merge pull request #628 from alfrunes/MEN-4874
Browse files Browse the repository at this point in the history
MEN-4874 Sort devices in deployment by status
  • Loading branch information
tranchitella committed Sep 10, 2021
2 parents be09d68 + 0c01a77 commit 4f648e2
Show file tree
Hide file tree
Showing 18 changed files with 1,205 additions and 556 deletions.
7 changes: 7 additions & 0 deletions api/http/api_deployments.go
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,13 @@ func (d *DeploymentsApiHandlers) GetDevicesListForDeployment(w rest.ResponseWrit
Limit: int(perPage),
DeploymentID: did,
}
if status := r.URL.Query().Get("status"); status != "" {
lq.Status = &status
}
if err = lq.Validate(); err != nil {
d.view.RenderError(w, r, err, http.StatusBadRequest, l)
return
}

statuses, totalCount, err := d.app.GetDevicesListForDeployment(ctx, lq)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -1206,12 +1206,12 @@ func (d *Deployments) createDeviceDeploymentWithStatus(
// in the database and locally, and update deployment status
if err := d.db.UpdateStatsInc(
ctx, deployment.Id,
model.DeviceDeploymentStatus(""), status,
model.DeviceDeploymentStatusNull, status,
); err != nil {
return nil, err
}

deployment.Stats[status]++
deployment.Stats.Inc(status)

err := d.recalcDeploymentStatus(ctx, deployment)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions app/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func TestUpdateDeviceDeploymentStatus(t *testing.T) {
model.DeviceDeploymentStatusInstalling).Return(nil)

// fake updated stats
fakeDeployment.Stats[model.DeviceDeploymentStatusInstalling] = 1
fakeDeployment.Stats.Set(model.DeviceDeploymentStatusInstalling, 1)

db.On("FindDeploymentByID", ctx, fakeDeployment.Id).Return(
fakeDeployment, nil)
Expand Down Expand Up @@ -161,7 +161,7 @@ func TestGetDeploymentForDeviceWithCurrent(t *testing.T) {
model.DeviceDeploymentStatusAlreadyInst).Return(nil)

// fake updated stats
fakeDeployment.Stats[model.DeviceDeploymentStatusNoArtifact] = 1
fakeDeployment.Stats.Set(model.DeviceDeploymentStatusNoArtifact, 1)
db.On("FindDeploymentByID", ctx, fakeDeployment.Id).Return(
fakeDeployment, nil)

Expand Down
62 changes: 44 additions & 18 deletions docs/management_api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ paths:
/deployments/{deployment_id}/devices:
get:
deprecated: true
operationId: List Devices in Deployment
operationId: List All Devices in Deployment
tags:
- Management API
security:
Expand Down Expand Up @@ -390,7 +390,7 @@ paths:

/deployments/{deployment_id}/devices/list:
get:
operationId: List Devices in Deployment with pagination
operationId: List Devices in Deployment
tags:
- Management API
security:
Expand All @@ -404,6 +404,27 @@ paths:
description: Deployment identifier.
required: true
type: string
- name: status
in: query
description: >-
Filter devices by status within deployment.
type: string
enum: # Unfortunately swagger 2.0 does not support reuse of enums.
- "failure"
- "aborted"
- "pause_before_installing"
- "pause_before_committing"
- "pause_before_rebooting"
- "downloading"
- "installing"
- "rebooting"
- "pending"
- "success"
- "noartifact"
- "already-installed"
- "decommissioned"
- "pause"
required: false
- name: page
in: query
description: Starting page.
Expand All @@ -417,7 +438,8 @@ paths:
required: false
type: number
format: integer
default: 10
default: 20
maximum: 500
produces:
- application/json
responses:
Expand Down Expand Up @@ -1130,21 +1152,7 @@ definitions:
type: string
format: date-time
status:
type: string
enum:
- downloading
- installing
- pause_before_installing
- pause_before_rebooting
- pause_before_committing
- rebooting
- pending
- success
- failure
- noartifact
- already-installed
- aborted
- decommissioned
$ref: '#/definitions/DeviceStatus'
created:
type: string
format: date-time
Expand Down Expand Up @@ -1331,6 +1339,24 @@ definitions:
example:
uri: http://mender.io/artifact.tar.gz.mender
expire: 2016-10-29T10:45:34Z

DeviceStatus:
type: string
enum:
- "failure"
- "aborted"
- "pause_before_installing"
- "pause_before_committing"
- "pause_before_rebooting"
- "downloading"
- "installing"
- "rebooting"
- "pending"
- "success"
- "noartifact"
- "already-installed"
- "decommissioned"

StorageLimit:
description: Tenant account storage limit and storage usage.
type: object
Expand Down
34 changes: 17 additions & 17 deletions model/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,17 +222,17 @@ func (d *Deployment) MarshalJSON() ([]byte, error) {
}

func (d *Deployment) IsNotPending() bool {
if d.Stats[DeviceDeploymentStatusDownloading] > 0 ||
d.Stats[DeviceDeploymentStatusInstalling] > 0 ||
d.Stats[DeviceDeploymentStatusRebooting] > 0 ||
d.Stats[DeviceDeploymentStatusSuccess] > 0 ||
d.Stats[DeviceDeploymentStatusAlreadyInst] > 0 ||
d.Stats[DeviceDeploymentStatusFailure] > 0 ||
d.Stats[DeviceDeploymentStatusAborted] > 0 ||
d.Stats[DeviceDeploymentStatusNoArtifact] > 0 ||
d.Stats[DeviceDeploymentStatusPauseBeforeInstall] > 0 ||
d.Stats[DeviceDeploymentStatusPauseBeforeCommit] > 0 ||
d.Stats[DeviceDeploymentStatusPauseBeforeReboot] > 0 {
if d.Stats[DeviceDeploymentStatusDownloadingStr] > 0 ||
d.Stats[DeviceDeploymentStatusInstallingStr] > 0 ||
d.Stats[DeviceDeploymentStatusRebootingStr] > 0 ||
d.Stats[DeviceDeploymentStatusSuccessStr] > 0 ||
d.Stats[DeviceDeploymentStatusAlreadyInstStr] > 0 ||
d.Stats[DeviceDeploymentStatusFailureStr] > 0 ||
d.Stats[DeviceDeploymentStatusAbortedStr] > 0 ||
d.Stats[DeviceDeploymentStatusNoArtifactStr] > 0 ||
d.Stats[DeviceDeploymentStatusPauseBeforeInstallStr] > 0 ||
d.Stats[DeviceDeploymentStatusPauseBeforeCommitStr] > 0 ||
d.Stats[DeviceDeploymentStatusPauseBeforeRebootStr] > 0 {

return true
}
Expand All @@ -242,12 +242,12 @@ func (d *Deployment) IsNotPending() bool {

func (d *Deployment) IsFinished() bool {
if d.Finished != nil ||
d.MaxDevices > 0 && ((d.Stats[DeviceDeploymentStatusAlreadyInst]+
d.Stats[DeviceDeploymentStatusSuccess]+
d.Stats[DeviceDeploymentStatusFailure]+
d.Stats[DeviceDeploymentStatusNoArtifact]+
d.Stats[DeviceDeploymentStatusDecommissioned]+
d.Stats[DeviceDeploymentStatusAborted]) >= d.MaxDevices) {
d.MaxDevices > 0 && ((d.Stats[DeviceDeploymentStatusAlreadyInstStr]+
d.Stats[DeviceDeploymentStatusSuccessStr]+
d.Stats[DeviceDeploymentStatusFailureStr]+
d.Stats[DeviceDeploymentStatusNoArtifactStr]+
d.Stats[DeviceDeploymentStatusDecommissionedStr]+
d.Stats[DeviceDeploymentStatusAbortedStr]) >= d.MaxDevices) {
return true
}

Expand Down
82 changes: 41 additions & 41 deletions model/deployment_external_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ func TestDeploymentIs(t *testing.T) {
for _, as := range active {
t.Logf("checking in-progress deployment stat %s", as)
d.Stats = NewDeviceDeploymentStats()
d.Stats[as] = 1
d.Stats.Set(as, 1)
assert.True(t, d.IsNotPending())
assert.False(t, d.IsFinished())
}
Expand All @@ -270,7 +270,7 @@ func TestDeploymentIs(t *testing.T) {
for _, as := range finished {
t.Logf("checking finished deployment stat %s", as)
d.Stats = NewDeviceDeploymentStats()
d.Stats[as] = 1
d.Stats.Set(as, 1)
assert.True(t, d.IsFinished())
assert.True(t, d.IsNotPending())
}
Expand All @@ -281,7 +281,7 @@ func TestDeploymentIs(t *testing.T) {
for _, as := range pending {
t.Logf("checking pending deployment stat %s", as)
d.Stats = NewDeviceDeploymentStats()
d.Stats[as] = 1
d.Stats.Set(as, 1)
assert.False(t, d.IsFinished())
assert.False(t, d.IsNotPending())
}
Expand All @@ -295,85 +295,85 @@ func TestDeploymentGetStatus(t *testing.T) {
}{
"Single NoArtifact": {
Stats: Stats{
DeviceDeploymentStatusNoArtifact: 1,
DeviceDeploymentStatusNoArtifactStr: 1,
},
OutputStatus: "finished",
},
"Single Success": {
Stats: Stats{
DeviceDeploymentStatusSuccess: 1,
DeviceDeploymentStatusSuccessStr: 1,
},
OutputStatus: "finished",
},
"Success + NoArtifact": {
Stats: Stats{
DeviceDeploymentStatusSuccess: 1,
DeviceDeploymentStatusNoArtifact: 1,
DeviceDeploymentStatusSuccessStr: 1,
DeviceDeploymentStatusNoArtifactStr: 1,
},
OutputStatus: "finished",
},
"Failed + NoArtifact": {
Stats: Stats{
DeviceDeploymentStatusFailure: 1,
DeviceDeploymentStatusNoArtifact: 1,
DeviceDeploymentStatusFailureStr: 1,
DeviceDeploymentStatusNoArtifactStr: 1,
},
OutputStatus: "finished",
},
"Failed + AlreadyInst": {
Stats: Stats{
DeviceDeploymentStatusFailure: 1,
DeviceDeploymentStatusAlreadyInst: 1,
DeviceDeploymentStatusFailureStr: 1,
DeviceDeploymentStatusAlreadyInstStr: 1,
},
OutputStatus: "finished",
},
"Failed + Aborted": {
Stats: Stats{
DeviceDeploymentStatusFailure: 1,
DeviceDeploymentStatusAborted: 1,
DeviceDeploymentStatusFailureStr: 1,
DeviceDeploymentStatusAbortedStr: 1,
},
OutputStatus: "finished",
},
"Rebooting + NoArtifact": {
Stats: Stats{
DeviceDeploymentStatusRebooting: 1,
DeviceDeploymentStatusNoArtifact: 1,
DeviceDeploymentStatusRebootingStr: 1,
DeviceDeploymentStatusNoArtifactStr: 1,
},
OutputStatus: "inprogress",
},
"Rebooting + Installing": {
Stats: Stats{
DeviceDeploymentStatusRebooting: 1,
DeviceDeploymentStatusInstalling: 1,
DeviceDeploymentStatusRebootingStr: 1,
DeviceDeploymentStatusInstallingStr: 1,
},
OutputStatus: "inprogress",
},
"Rebooting + Pending": {
Stats: Stats{
DeviceDeploymentStatusRebooting: 1,
DeviceDeploymentStatusPending: 1,
DeviceDeploymentStatusRebootingStr: 1,
DeviceDeploymentStatusPendingStr: 1,
},
OutputStatus: "inprogress",
},
"All paused states": {
Stats: Stats{
DeviceDeploymentStatusPauseBeforeInstall: 1,
DeviceDeploymentStatusPauseBeforeCommit: 1,
DeviceDeploymentStatusPauseBeforeReboot: 1,
DeviceDeploymentStatusPauseBeforeInstallStr: 1,
DeviceDeploymentStatusPauseBeforeCommitStr: 1,
DeviceDeploymentStatusPauseBeforeRebootStr: 1,
},
OutputStatus: "inprogress",
},
"Some paused states": {
Stats: Stats{
DeviceDeploymentStatusInstalling: 1,
DeviceDeploymentStatusPauseBeforeInstall: 1,
DeviceDeploymentStatusPauseBeforeCommit: 0,
DeviceDeploymentStatusPauseBeforeReboot: 1,
DeviceDeploymentStatusInstallingStr: 1,
DeviceDeploymentStatusPauseBeforeInstallStr: 1,
DeviceDeploymentStatusPauseBeforeCommitStr: 0,
DeviceDeploymentStatusPauseBeforeRebootStr: 1,
},
OutputStatus: "inprogress",
},
"Pending": {
Stats: Stats{
DeviceDeploymentStatusPending: 1,
DeviceDeploymentStatusPendingStr: 1,
},
OutputStatus: "pending",
},
Expand All @@ -383,16 +383,16 @@ func TestDeploymentGetStatus(t *testing.T) {
//verify we count 'already-installed' towards 'inprogress'
"pending + already-installed": {
Stats: Stats{
DeviceDeploymentStatusPending: 1,
DeviceDeploymentStatusAlreadyInst: 1,
DeviceDeploymentStatusPendingStr: 1,
DeviceDeploymentStatusAlreadyInstStr: 1,
},
OutputStatus: "inprogress",
},
//verify we count 'already-installed' towards 'finished'
"already-installed + finished": {
Stats: Stats{
DeviceDeploymentStatusPending: 0,
DeviceDeploymentStatusAlreadyInst: 1,
DeviceDeploymentStatusPendingStr: 0,
DeviceDeploymentStatusAlreadyInstStr: 1,
},
OutputStatus: "finished",
},
Expand Down Expand Up @@ -428,16 +428,16 @@ func TestFuzzyGetStatus(t *testing.T) {
dep, err := NewDeployment()
assert.NoError(t, err)

dep.Stats[DeviceDeploymentStatusDownloading] = rand(0, max)
dep.Stats[DeviceDeploymentStatusInstalling] = rand(0, max)
dep.Stats[DeviceDeploymentStatusRebooting] = rand(0, max)
dep.Stats[DeviceDeploymentStatusPending] = rand(0, max)
dep.Stats[DeviceDeploymentStatusSuccess] = rand(0, max)
dep.Stats[DeviceDeploymentStatusFailure] = rand(0, max)
dep.Stats[DeviceDeploymentStatusNoArtifact] = rand(0, max)
dep.Stats[DeviceDeploymentStatusAlreadyInst] = rand(0, max)
dep.Stats[DeviceDeploymentStatusAborted] = rand(0, max)
dep.Stats[DeviceDeploymentStatusDecommissioned] = rand(0, max)
dep.Stats[DeviceDeploymentStatusDownloadingStr] = rand(0, max)
dep.Stats[DeviceDeploymentStatusInstallingStr] = rand(0, max)
dep.Stats[DeviceDeploymentStatusRebootingStr] = rand(0, max)
dep.Stats[DeviceDeploymentStatusPendingStr] = rand(0, max)
dep.Stats[DeviceDeploymentStatusSuccessStr] = rand(0, max)
dep.Stats[DeviceDeploymentStatusFailureStr] = rand(0, max)
dep.Stats[DeviceDeploymentStatusNoArtifactStr] = rand(0, max)
dep.Stats[DeviceDeploymentStatusAlreadyInstStr] = rand(0, max)
dep.Stats[DeviceDeploymentStatusAbortedStr] = rand(0, max)
dep.Stats[DeviceDeploymentStatusDecommissionedStr] = rand(0, max)

pending := 0
inprogress := 0
Expand Down
Loading

0 comments on commit 4f648e2

Please sign in to comment.