Skip to content

Commit

Permalink
feat: support idling and unidling from api with idled status on envir…
Browse files Browse the repository at this point in the history
…onment
  • Loading branch information
shreddedbacon committed Nov 26, 2024
1 parent 7bc11f0 commit c5f1617
Show file tree
Hide file tree
Showing 10 changed files with 302 additions and 15 deletions.
10 changes: 8 additions & 2 deletions node-packages/commons/src/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1196,9 +1196,7 @@ export const createMiscTask = async function(taskData: any) {
data: { project }
} = taskData;

// handle any controller based misc tasks
let updatedKey = `deploytarget:${key}`;
let taskId = 'misc-kubernetes';
// determine the deploy target (openshift/kubernetes) for the task to go to
// we get this from the environment
const result = await getOpenShiftInfoForEnvironment(taskData.data.environment.id);
Expand Down Expand Up @@ -1373,6 +1371,14 @@ export const createMiscTask = async function(taskData: any) {
// build cancellation is just a standard unmodified message
miscTaskData.misc = taskData.data.build
break;
case 'deploytarget:environment:idling':
// environment idling is used to handle idling or unidling of an an environment
miscTaskData.idling = taskData.data.idling
break;
case 'deploytarget:environment:service':
// environment service is used to handle stop, start, or restarting of a service in an environment
miscTaskData.lagoonService = taskData.data.lagoonService
break;
default:
miscTaskData.misc = taskData.data.build
break;
Expand Down
2 changes: 1 addition & 1 deletion services/actions-handler/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.22

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

Expand Down
2 changes: 2 additions & 0 deletions services/actions-handler/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,8 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/uselagoon/machinery v0.0.29 h1:invFIPv1Z1xCt8/1ilbiNDuAEPrb+AUO21BnNG+CX8c=
github.com/uselagoon/machinery v0.0.29/go.mod h1:X0qguIO9skumMhhT0ap5CKHulKgYzy3TiIn+xlwiFQc=
github.com/uselagoon/machinery v0.0.32-0.20241126220946-4920362e8581 h1:bO1A3yn6veMrz30ANsGnWYvsya7Ato3GgUHYPmoX96M=
github.com/uselagoon/machinery v0.0.32-0.20241126220946-4920362e8581/go.mod h1:RsHzIMOam3hiA4CKR12yANgzdTGy6tz4D19umjMzZyw=
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
Expand Down
94 changes: 94 additions & 0 deletions services/actions-handler/handler/controller_idling.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package handler

import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"log"
"time"

mq "github.com/cheshir/go-mq/v2"
"github.com/uselagoon/machinery/api/lagoon"
lclient "github.com/uselagoon/machinery/api/lagoon/client"
"github.com/uselagoon/machinery/api/schema"
"github.com/uselagoon/machinery/utils/jwt"
)

type Idled struct {
Idled bool `json:"idled"`
}

func (m *Messenger) handleIdling(ctx context.Context, messageQueue *mq.MessageQueue, message *schema.LagoonMessage, messageID string) error {
prefix := fmt.Sprintf("(messageid:%s) %s: ", messageID, message.Namespace)
log.Println(fmt.Sprintf("%sreceived idling environment status update", prefix))
// generate a lagoon token with a expiry of 60 seconds from now
token, err := jwt.GenerateAdminToken(m.LagoonAPI.TokenSigningKey, m.LagoonAPI.JWTAudience, m.LagoonAPI.JWTSubject, m.LagoonAPI.JWTIssuer, time.Now().Unix(), 60)
if err != nil {
// the token wasn't generated
if m.EnableDebug {
log.Println(fmt.Sprintf("ERROR: unable to generate token: %v", err))
}
return nil
}
// set up a lagoon client for use in the following process
l := lclient.New(m.LagoonAPI.Endpoint, "actions-handler", m.LagoonAPI.Version, &token, false)
var environmentID uint
// determine the environment id from the message
if message.Meta.ProjectID == nil && message.Meta.EnvironmentID == nil {
project, err := lagoon.GetMinimalProjectByName(ctx, message.Meta.Project, l)
if err != nil {
// send the log to the lagoon-logs exchange to be processed
m.toLagoonLogs(messageQueue, map[string]interface{}{
"severity": "error",
"event": fmt.Sprintf("actions-handler:%s:failed", "updateEnvironment"),
"meta": project,
"message": err.Error(),
})
if m.EnableDebug {
log.Println(fmt.Sprintf("%sERROR: unable to get project - %v", prefix, err))
}
return err
}
environment, err := lagoon.GetEnvironmentByName(ctx, message.Meta.Environment, project.ID, l)
if err != nil {
// send the log to the lagoon-logs exchange to be processed
m.toLagoonLogs(messageQueue, map[string]interface{}{
"severity": "error",
"event": fmt.Sprintf("actions-handler:%s:failed", "updateEnvironment"),
"meta": project,
"message": err.Error(),
})
if m.EnableDebug {
log.Println(fmt.Sprintf("%sERROR: unable to get environment - %v", prefix, err))
}
return err
}
environmentID = environment.ID
} else {
// pull the id from the message
environmentID = *message.Meta.EnvironmentID
}
decodeData, _ := base64.StdEncoding.DecodeString(message.Meta.AdvancedData)
idled := &Idled{}
json.Unmarshal(decodeData, idled)
updateEnvironmentPatch := schema.UpdateEnvironmentPatchInput{
Idled: &idled.Idled,
}
updateEnvironment, err := lagoon.UpdateEnvironment(ctx, environmentID, updateEnvironmentPatch, l)
if err != nil {
// send the log to the lagoon-logs exchange to be processed
m.toLagoonLogs(messageQueue, map[string]interface{}{
"severity": "error",
"event": fmt.Sprintf("actions-handler:%s:failed", "updateDeployment"),
"meta": updateEnvironment,
"message": err.Error(),
})
if m.EnableDebug {
log.Println(fmt.Sprintf("%sERROR: unable to update environment - %v", prefix, err))
}
return err
}
log.Println(fmt.Sprintf("%supdated environment", prefix))
return nil
}
16 changes: 8 additions & 8 deletions services/actions-handler/handler/controller_tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ import (

func (m *Messenger) handleTask(ctx context.Context, messageQueue *mq.MessageQueue, message *schema.LagoonMessage, messageID string) error {
prefix := fmt.Sprintf("(messageid:%s) %s/%s: ", messageID, message.Namespace, message.Meta.Task.Name)
log.Println(fmt.Sprintf("%sreceived task status update: %s", prefix, message.Meta.JobStatus))
log.Printf("%sreceived task status update: %s", prefix, message.Meta.JobStatus)
// generate a lagoon token with a expiry of 60 seconds from now
token, err := jwt.GenerateAdminToken(m.LagoonAPI.TokenSigningKey, m.LagoonAPI.JWTAudience, m.LagoonAPI.JWTSubject, m.LagoonAPI.JWTIssuer, time.Now().Unix(), 60)
if err != nil {
// the token wasn't generated
if m.EnableDebug {
log.Println(fmt.Sprintf("%sERROR: unable to generate token: %v", prefix, err))
log.Printf("%sERROR: unable to generate token: %v", prefix, err)
}
return nil
}
Expand All @@ -48,7 +48,7 @@ func (m *Messenger) handleTask(ctx context.Context, messageQueue *mq.MessageQueu
"message": err.Error(),
})
if m.EnableDebug {
log.Println(fmt.Sprintf("%sERROR: unable to project information: %v", prefix, err))
log.Printf("%sERROR: unable to project information: %v", prefix, err)
}
return err
}
Expand All @@ -70,7 +70,7 @@ func (m *Messenger) handleTask(ctx context.Context, messageQueue *mq.MessageQueu
updateProject.StandbyProductionEnvironment = &advTask.ProductionEnvironment
}
// update the project in the api
updatedProject, err := lagoon.UpdateProject(ctx, int(project.ID), updateProject, l)
updatedProject, err := lagoon.UpdateProject(ctx, project.ID, updateProject, l)
if err != nil {
// send the log to the lagoon-logs exchange to be processed
m.toLagoonLogs(messageQueue, map[string]interface{}{
Expand All @@ -80,11 +80,11 @@ func (m *Messenger) handleTask(ctx context.Context, messageQueue *mq.MessageQueu
"message": err.Error(),
})
if m.EnableDebug {
log.Println(fmt.Sprintf("%sERROR: unable to update project with active/standby result: %v", prefix, err))
log.Printf("%sERROR: unable to update project with active/standby result: %v", prefix, err)
}
return err
}
log.Println(fmt.Sprintf("%supdated project %s with active/standby result: %v", prefix, message.Meta.Project, "success"))
log.Printf("%supdated project %s with active/standby result: %v", prefix, message.Meta.Project, "success")
}
}
// continue on to updating the task as normal
Expand Down Expand Up @@ -113,10 +113,10 @@ func (m *Messenger) handleTask(ctx context.Context, messageQueue *mq.MessageQueu
"message": err.Error(),
})
if m.EnableDebug {
log.Println(fmt.Sprintf("%sERROR: unable to update task: %v", prefix, err))
log.Printf("%sERROR: unable to update task: %v", prefix, err)
}
return err
}
log.Println(fmt.Sprintf("%supdated task: %s", prefix, message.Meta.JobStatus))
log.Printf("%supdated task: %s", prefix, message.Meta.JobStatus)
return nil
}
2 changes: 2 additions & 0 deletions services/actions-handler/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ func (m *Messenger) Consumer() {
err = m.handleRemoval(ctx, messageQueue, logMsg, messageID)
case "task":
err = m.handleTask(ctx, messageQueue, logMsg, messageID)
case "idling":
err = m.handleIdling(ctx, messageQueue, logMsg, messageID)
}
// 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
// skipping this means the message will remain in the queue
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.up = async function(knex) {
return knex.schema
.alterTable('environment', (table) => {
table.boolean('idled').notNullable().defaultTo(0);
})
};

/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.down = async function(knex) {
return knex.schema
.alterTable('environment', (table) => {
table.dropColumn('idled');
})
};
4 changes: 3 additions & 1 deletion services/api/src/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ const {
getEnvironmentByServiceId,
getServiceContainersByServiceId,
deleteEnvironmentService,
environmentIdling,
} = require('./resources/environment/resolvers');

const {
Expand Down Expand Up @@ -705,7 +706,8 @@ const resolvers = {
removeUserFromOrganizationGroups,
bulkImportProjectsAndGroupsToOrganization,
addOrUpdateEnvironmentService,
deleteEnvironmentService
deleteEnvironmentService,
environmentIdling,
},
Subscription: {
backupChanged: backupSubscriber,
Expand Down
Loading

0 comments on commit c5f1617

Please sign in to comment.