Skip to content

Commit c5f1617

Browse files
committed
feat: support idling and unidling from api with idled status on environment
1 parent 7bc11f0 commit c5f1617

File tree

10 files changed

+302
-15
lines changed

10 files changed

+302
-15
lines changed

node-packages/commons/src/tasks.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,9 +1196,7 @@ export const createMiscTask = async function(taskData: any) {
11961196
data: { project }
11971197
} = taskData;
11981198

1199-
// handle any controller based misc tasks
12001199
let updatedKey = `deploytarget:${key}`;
1201-
let taskId = 'misc-kubernetes';
12021200
// determine the deploy target (openshift/kubernetes) for the task to go to
12031201
// we get this from the environment
12041202
const result = await getOpenShiftInfoForEnvironment(taskData.data.environment.id);
@@ -1373,6 +1371,14 @@ export const createMiscTask = async function(taskData: any) {
13731371
// build cancellation is just a standard unmodified message
13741372
miscTaskData.misc = taskData.data.build
13751373
break;
1374+
case 'deploytarget:environment:idling':
1375+
// environment idling is used to handle idling or unidling of an an environment
1376+
miscTaskData.idling = taskData.data.idling
1377+
break;
1378+
case 'deploytarget:environment:service':
1379+
// environment service is used to handle stop, start, or restarting of a service in an environment
1380+
miscTaskData.lagoonService = taskData.data.lagoonService
1381+
break;
13761382
default:
13771383
miscTaskData.misc = taskData.data.build
13781384
break;

services/actions-handler/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.22
44

55
require (
66
github.com/cheshir/go-mq/v2 v2.0.1
7-
github.com/uselagoon/machinery v0.0.29
7+
github.com/uselagoon/machinery v0.0.32-0.20241126220946-4920362e8581
88
gopkg.in/matryer/try.v1 v1.0.0-20150601225556-312d2599e12e
99
)
1010

services/actions-handler/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,8 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX
844844
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
845845
github.com/uselagoon/machinery v0.0.29 h1:invFIPv1Z1xCt8/1ilbiNDuAEPrb+AUO21BnNG+CX8c=
846846
github.com/uselagoon/machinery v0.0.29/go.mod h1:X0qguIO9skumMhhT0ap5CKHulKgYzy3TiIn+xlwiFQc=
847+
github.com/uselagoon/machinery v0.0.32-0.20241126220946-4920362e8581 h1:bO1A3yn6veMrz30ANsGnWYvsya7Ato3GgUHYPmoX96M=
848+
github.com/uselagoon/machinery v0.0.32-0.20241126220946-4920362e8581/go.mod h1:RsHzIMOam3hiA4CKR12yANgzdTGy6tz4D19umjMzZyw=
847849
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
848850
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
849851
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package handler
2+
3+
import (
4+
"context"
5+
"encoding/base64"
6+
"encoding/json"
7+
"fmt"
8+
"log"
9+
"time"
10+
11+
mq "github.com/cheshir/go-mq/v2"
12+
"github.com/uselagoon/machinery/api/lagoon"
13+
lclient "github.com/uselagoon/machinery/api/lagoon/client"
14+
"github.com/uselagoon/machinery/api/schema"
15+
"github.com/uselagoon/machinery/utils/jwt"
16+
)
17+
18+
type Idled struct {
19+
Idled bool `json:"idled"`
20+
}
21+
22+
func (m *Messenger) handleIdling(ctx context.Context, messageQueue *mq.MessageQueue, message *schema.LagoonMessage, messageID string) error {
23+
prefix := fmt.Sprintf("(messageid:%s) %s: ", messageID, message.Namespace)
24+
log.Println(fmt.Sprintf("%sreceived idling environment status update", prefix))
25+
// generate a lagoon token with a expiry of 60 seconds from now
26+
token, err := jwt.GenerateAdminToken(m.LagoonAPI.TokenSigningKey, m.LagoonAPI.JWTAudience, m.LagoonAPI.JWTSubject, m.LagoonAPI.JWTIssuer, time.Now().Unix(), 60)
27+
if err != nil {
28+
// the token wasn't generated
29+
if m.EnableDebug {
30+
log.Println(fmt.Sprintf("ERROR: unable to generate token: %v", err))
31+
}
32+
return nil
33+
}
34+
// set up a lagoon client for use in the following process
35+
l := lclient.New(m.LagoonAPI.Endpoint, "actions-handler", m.LagoonAPI.Version, &token, false)
36+
var environmentID uint
37+
// determine the environment id from the message
38+
if message.Meta.ProjectID == nil && message.Meta.EnvironmentID == nil {
39+
project, err := lagoon.GetMinimalProjectByName(ctx, message.Meta.Project, l)
40+
if err != nil {
41+
// send the log to the lagoon-logs exchange to be processed
42+
m.toLagoonLogs(messageQueue, map[string]interface{}{
43+
"severity": "error",
44+
"event": fmt.Sprintf("actions-handler:%s:failed", "updateEnvironment"),
45+
"meta": project,
46+
"message": err.Error(),
47+
})
48+
if m.EnableDebug {
49+
log.Println(fmt.Sprintf("%sERROR: unable to get project - %v", prefix, err))
50+
}
51+
return err
52+
}
53+
environment, err := lagoon.GetEnvironmentByName(ctx, message.Meta.Environment, project.ID, l)
54+
if err != nil {
55+
// send the log to the lagoon-logs exchange to be processed
56+
m.toLagoonLogs(messageQueue, map[string]interface{}{
57+
"severity": "error",
58+
"event": fmt.Sprintf("actions-handler:%s:failed", "updateEnvironment"),
59+
"meta": project,
60+
"message": err.Error(),
61+
})
62+
if m.EnableDebug {
63+
log.Println(fmt.Sprintf("%sERROR: unable to get environment - %v", prefix, err))
64+
}
65+
return err
66+
}
67+
environmentID = environment.ID
68+
} else {
69+
// pull the id from the message
70+
environmentID = *message.Meta.EnvironmentID
71+
}
72+
decodeData, _ := base64.StdEncoding.DecodeString(message.Meta.AdvancedData)
73+
idled := &Idled{}
74+
json.Unmarshal(decodeData, idled)
75+
updateEnvironmentPatch := schema.UpdateEnvironmentPatchInput{
76+
Idled: &idled.Idled,
77+
}
78+
updateEnvironment, err := lagoon.UpdateEnvironment(ctx, environmentID, updateEnvironmentPatch, l)
79+
if err != nil {
80+
// send the log to the lagoon-logs exchange to be processed
81+
m.toLagoonLogs(messageQueue, map[string]interface{}{
82+
"severity": "error",
83+
"event": fmt.Sprintf("actions-handler:%s:failed", "updateDeployment"),
84+
"meta": updateEnvironment,
85+
"message": err.Error(),
86+
})
87+
if m.EnableDebug {
88+
log.Println(fmt.Sprintf("%sERROR: unable to update environment - %v", prefix, err))
89+
}
90+
return err
91+
}
92+
log.Println(fmt.Sprintf("%supdated environment", prefix))
93+
return nil
94+
}

services/actions-handler/handler/controller_tasks.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ import (
1919

2020
func (m *Messenger) handleTask(ctx context.Context, messageQueue *mq.MessageQueue, message *schema.LagoonMessage, messageID string) error {
2121
prefix := fmt.Sprintf("(messageid:%s) %s/%s: ", messageID, message.Namespace, message.Meta.Task.Name)
22-
log.Println(fmt.Sprintf("%sreceived task status update: %s", prefix, message.Meta.JobStatus))
22+
log.Printf("%sreceived task status update: %s", prefix, message.Meta.JobStatus)
2323
// generate a lagoon token with a expiry of 60 seconds from now
2424
token, err := jwt.GenerateAdminToken(m.LagoonAPI.TokenSigningKey, m.LagoonAPI.JWTAudience, m.LagoonAPI.JWTSubject, m.LagoonAPI.JWTIssuer, time.Now().Unix(), 60)
2525
if err != nil {
2626
// the token wasn't generated
2727
if m.EnableDebug {
28-
log.Println(fmt.Sprintf("%sERROR: unable to generate token: %v", prefix, err))
28+
log.Printf("%sERROR: unable to generate token: %v", prefix, err)
2929
}
3030
return nil
3131
}
@@ -48,7 +48,7 @@ func (m *Messenger) handleTask(ctx context.Context, messageQueue *mq.MessageQueu
4848
"message": err.Error(),
4949
})
5050
if m.EnableDebug {
51-
log.Println(fmt.Sprintf("%sERROR: unable to project information: %v", prefix, err))
51+
log.Printf("%sERROR: unable to project information: %v", prefix, err)
5252
}
5353
return err
5454
}
@@ -70,7 +70,7 @@ func (m *Messenger) handleTask(ctx context.Context, messageQueue *mq.MessageQueu
7070
updateProject.StandbyProductionEnvironment = &advTask.ProductionEnvironment
7171
}
7272
// update the project in the api
73-
updatedProject, err := lagoon.UpdateProject(ctx, int(project.ID), updateProject, l)
73+
updatedProject, err := lagoon.UpdateProject(ctx, project.ID, updateProject, l)
7474
if err != nil {
7575
// send the log to the lagoon-logs exchange to be processed
7676
m.toLagoonLogs(messageQueue, map[string]interface{}{
@@ -80,11 +80,11 @@ func (m *Messenger) handleTask(ctx context.Context, messageQueue *mq.MessageQueu
8080
"message": err.Error(),
8181
})
8282
if m.EnableDebug {
83-
log.Println(fmt.Sprintf("%sERROR: unable to update project with active/standby result: %v", prefix, err))
83+
log.Printf("%sERROR: unable to update project with active/standby result: %v", prefix, err)
8484
}
8585
return err
8686
}
87-
log.Println(fmt.Sprintf("%supdated project %s with active/standby result: %v", prefix, message.Meta.Project, "success"))
87+
log.Printf("%supdated project %s with active/standby result: %v", prefix, message.Meta.Project, "success")
8888
}
8989
}
9090
// continue on to updating the task as normal
@@ -113,10 +113,10 @@ func (m *Messenger) handleTask(ctx context.Context, messageQueue *mq.MessageQueu
113113
"message": err.Error(),
114114
})
115115
if m.EnableDebug {
116-
log.Println(fmt.Sprintf("%sERROR: unable to update task: %v", prefix, err))
116+
log.Printf("%sERROR: unable to update task: %v", prefix, err)
117117
}
118118
return err
119119
}
120-
log.Println(fmt.Sprintf("%supdated task: %s", prefix, message.Meta.JobStatus))
120+
log.Printf("%supdated task: %s", prefix, message.Meta.JobStatus)
121121
return nil
122122
}

services/actions-handler/handler/handler.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ func (m *Messenger) Consumer() {
143143
err = m.handleRemoval(ctx, messageQueue, logMsg, messageID)
144144
case "task":
145145
err = m.handleTask(ctx, messageQueue, logMsg, messageID)
146+
case "idling":
147+
err = m.handleIdling(ctx, messageQueue, logMsg, messageID)
146148
}
147149
// if there aren't any errors, then ack the message, an error indicates that there may have been an issue with the api handling the request
148150
// skipping this means the message will remain in the queue
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* @param { import("knex").Knex } knex
3+
* @returns { Promise<void> }
4+
*/
5+
exports.up = async function(knex) {
6+
return knex.schema
7+
.alterTable('environment', (table) => {
8+
table.boolean('idled').notNullable().defaultTo(0);
9+
})
10+
};
11+
12+
/**
13+
* @param { import("knex").Knex } knex
14+
* @returns { Promise<void> }
15+
*/
16+
exports.down = async function(knex) {
17+
return knex.schema
18+
.alterTable('environment', (table) => {
19+
table.dropColumn('idled');
20+
})
21+
};

services/api/src/resolvers.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ const {
124124
getEnvironmentByServiceId,
125125
getServiceContainersByServiceId,
126126
deleteEnvironmentService,
127+
environmentIdling,
127128
} = require('./resources/environment/resolvers');
128129

129130
const {
@@ -705,7 +706,8 @@ const resolvers = {
705706
removeUserFromOrganizationGroups,
706707
bulkImportProjectsAndGroupsToOrganization,
707708
addOrUpdateEnvironmentService,
708-
deleteEnvironmentService
709+
deleteEnvironmentService,
710+
environmentIdling,
709711
},
710712
Subscription: {
711713
backupChanged: backupSubscriber,

0 commit comments

Comments
 (0)