Skip to content

Commit

Permalink
Merge pull request #60 from Phillezi/bugfixes
Browse files Browse the repository at this point in the history
some bugfixes + stop command
  • Loading branch information
Phillezi authored Dec 26, 2024
2 parents e758b91 + 90213c6 commit 20c2880
Show file tree
Hide file tree
Showing 7 changed files with 309 additions and 32 deletions.
21 changes: 20 additions & 1 deletion cmd/cli_compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,24 @@ var composeUpCmd = &cobra.Command{
}
var composeDownCmd = &cobra.Command{
Use: "down",
Short: "Bring down compose configuration to cloud",
Run: func(cmd *cobra.Command, args []string) {
all, err := cmd.Flags().GetBool("all")
if err != nil {
logrus.Fatal(err)
}
volumes, err := cmd.Flags().GetBool("volumes")
if err != nil {
logrus.Fatal(err)
}
compose.Down(all, volumes)
},
}
var composeStopCmd = &cobra.Command{
Use: "stop",
Short: "Stop compose configuration to cloud",
Run: func(cmd *cobra.Command, args []string) {
compose.Down()
compose.Stop()
},
}
var composeLogsCmd = &cobra.Command{
Expand Down Expand Up @@ -75,10 +90,14 @@ func init() {
buildF := composeUpCmd.Flags().Lookup("build")
buildF.NoOptDefVal = "__all__"

composeDownCmd.Flags().BoolP("all", "a", false, "Remove all")
composeDownCmd.Flags().BoolP("volumes", "v", false, "Remove volumes")

// Register subcommands with the main compose command
composeCmd.AddCommand(composeParseCmd)
composeCmd.AddCommand(composeUpCmd)
composeCmd.AddCommand(composeDownCmd)
composeCmd.AddCommand(composeStopCmd)
composeCmd.AddCommand(composeLogsCmd)
composeCmd.AddCommand(testSMAuthCmd)

Expand Down
8 changes: 8 additions & 0 deletions pkg/util/strings.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,11 @@ func TimeAgo(t *time.Time) string {
return fmt.Sprintf("%dd ago", int(duration.Hours()/24))
}
}

func IsEmptyOrNil(image *string) bool {
return image == nil || *image == ""
}

func NotNilOrEmpty(image *string) bool {
return image != nil && *image != ""
}
2 changes: 1 addition & 1 deletion pkg/v1/auth/client/exists.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (c *Client) DeploymentExistsByNameWFilter(name string, filter func(depl bod
}
for _, depl := range depls {
if depl.Name == name && filter(depl) {
return true, depl.ID, false
return true, depl.ID, true
} else if depl.Name == name {
// depl with the same name exists but it doesnt match the filter
return true, depl.ID, false
Expand Down
71 changes: 48 additions & 23 deletions pkg/v1/commands/compose/down.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package compose

import (
"context"
"go-deploy/dto/v2/body"
"sync"
"time"

"github.com/Phillezi/kthcloud-cli/pkg/scheduler"
"github.com/Phillezi/kthcloud-cli/pkg/util"
"github.com/Phillezi/kthcloud-cli/pkg/v1/auth/client"
"github.com/Phillezi/kthcloud-cli/pkg/v1/commands/compose/jobs"
Expand All @@ -14,7 +15,20 @@ import (
"github.com/sirupsen/logrus"
)

func Down() {
func Down(all, volumes bool) {
ctx, cancelStop := context.WithCancel(context.Background())
done := make(chan bool)
scheduleContext, cancelScheduler := context.WithCancel(ctx)
sched := scheduler.NewSched(scheduleContext)

s := spinner.New(spinner.CharSets[14], 100*time.Millisecond)

util.SetupSignalHandler(done, func() {
sched.CancelJobsBlock()
cancelStop()
<-ctx.Done()
})

composeInstance, err := parser.GetCompose()
if err != nil {
logrus.Fatal(err)
Expand All @@ -35,36 +49,47 @@ func Down() {
deploymentMap[depl.Name] = &depl
}

var wg sync.WaitGroup
go sched.Start()
defer cancelScheduler()

s := spinner.New(spinner.CharSets[14], 100*time.Millisecond)
s.Color("blue")
s.Start()
defer s.Stop()

jobIDs := make(map[string]string)

for name := range composeInstance.Services {
if deployment, exists := deploymentMap[name]; exists {
if deployment.Image == nil {
logrus.Infoln("Skipping deletion of deployment:", deployment.Name, ". Since it is a custom deployment (cicd)")
if !all && deployment.Image == nil {
logrus.Infoln("Skipping deletion of deployment:", deployment.Name, ". Since it is a custom deployment (cicd)\n\nUse:\n\t--all\n\nTo remove CICD deployments too")
continue
}
resp, err := c.Remove(deployment)
if err != nil {
logrus.Fatal(err)
}
err = response.IsError(resp.String())
if err != nil {
logrus.Fatal(err)
}
job, err := util.ProcessResponse[body.DeploymentDeleted](resp.String())
if err != nil {
logrus.Errorln(resp.String())
logrus.Fatal(err)
}
jobs.TrackDeploymentDeletionW(deployment.Name, job, &wg, s)

jobIDs[name] = sched.AddJob(scheduler.NewJob(func(ctx context.Context, cancelCallback func()) error {
resp, err := c.Remove(deployment)
if err != nil {
logrus.Error(err)
return err
}
err = response.IsError(resp.String())
if err != nil {
logrus.Error(err)
return err
}
job, err := util.ProcessResponse[body.DeploymentDeleted](resp.String())
if err != nil {
logrus.Error(err)
return err
}
return jobs.From(job).Track(ctx, deployment.Name, time.Millisecond*500, cancelCallback)
}, func() {}))
}
}
wg.Wait()
s.Color("green")
s.Stop()
if err := jobs.MonitorJobStates(jobIDs, sched, s); err != nil {
logrus.Debugln("erroccurred")
s.Color("red")
} else {
logrus.Debugln("alldone")
s.Color("green")
}
}
113 changes: 113 additions & 0 deletions pkg/v1/commands/compose/jobs/deployJob.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package jobs

import (
"context"
"fmt"
"go-deploy/dto/v2/body"
"strings"
"time"

"github.com/Phillezi/kthcloud-cli/pkg/util"
"github.com/Phillezi/kthcloud-cli/pkg/v1/auth/client"
"github.com/sirupsen/logrus"
)

type DeploymentJob struct {
Type string
ID string `json:"id"`
JobID *string `json:"jobId,omitempty"`
}

func From(job interface{}) *DeploymentJob {
switch v := job.(type) {
case *body.DeploymentCreated:
return &DeploymentJob{
Type: "Created",
ID: v.ID,
JobID: &v.JobID,
}
case *body.DeploymentUpdated:
return &DeploymentJob{
Type: "Updated",
ID: v.ID,
JobID: v.JobID,
}
case *body.DeploymentDeleted:
return &DeploymentJob{
Type: "Deleted",
ID: v.ID,
JobID: &v.JobID,
}
default:
logrus.Debugln("cant create DeploymentJob from this type")
return nil
}
}

func FromCreated(job *body.DeploymentCreated) *DeploymentJob {
return &DeploymentJob{
Type: "Created",
ID: job.ID,
JobID: &job.JobID,
}
}

func FromUpdated(job *body.DeploymentUpdated) *DeploymentJob {
return &DeploymentJob{
Type: "Updated",
ID: job.ID,
JobID: job.JobID,
}
}

func FromDeleted(job *body.DeploymentDeleted) *DeploymentJob {
return &DeploymentJob{
Type: "Deleted",
ID: job.ID,
JobID: &job.JobID,
}
}

func (job *DeploymentJob) Track(ctx context.Context, deploymentName string, tickerInterval time.Duration, onCancel func()) error {
if job.JobID == nil {
logrus.Debugln("no jobID to track")
}

c := client.Get().Client()
ticker := time.NewTicker(tickerInterval)
defer ticker.Stop()

for {
select {
case <-ctx.Done():
logrus.Debugf("deployment %s was cancelled\n", deploymentName)
if onCancel != nil {
onCancel()
}
return nil
case <-ticker.C:
jobResp, err := c.R().Get("/v2/jobs/" + *job.JobID)
if err != nil {
return fmt.Errorf("failed to get job status for deployment %s: %w", deploymentName, err)
}

jobStatus, err := util.ProcessResponse[body.JobRead](jobResp.String())
if err != nil {
return fmt.Errorf("error processing job status for deployment %s: %w", deploymentName, err)
}

switch jobStatus.Status {
case "finished":
logrus.Debugf("Deployment %s %s successfully", deploymentName, strings.ToLower(job.Type))
return nil
case "terminated":
logrus.Debugf("Job for deployment %s was terminated", deploymentName)
return nil
}

if jobStatus.LastError != nil {
return fmt.Errorf("failed to %s deployment %s: %s", strings.ToLower(strings.TrimSuffix(job.Type, "d")), deploymentName, *jobStatus.LastError)
}
}
}
}
96 changes: 96 additions & 0 deletions pkg/v1/commands/compose/stop.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package compose

import (
"context"
"go-deploy/dto/v2/body"
"time"

"github.com/Phillezi/kthcloud-cli/pkg/scheduler"
"github.com/Phillezi/kthcloud-cli/pkg/util"
"github.com/Phillezi/kthcloud-cli/pkg/v1/auth/client"
"github.com/Phillezi/kthcloud-cli/pkg/v1/commands/compose/jobs"
"github.com/Phillezi/kthcloud-cli/pkg/v1/commands/compose/parser"
"github.com/Phillezi/kthcloud-cli/pkg/v1/commands/compose/response"
"github.com/briandowns/spinner"
"github.com/sirupsen/logrus"
)

func Stop() {
ctx, cancelStop := context.WithCancel(context.Background())
done := make(chan bool)
scheduleContext, cancelScheduler := context.WithCancel(ctx)
sched := scheduler.NewSched(scheduleContext)

s := spinner.New(spinner.CharSets[14], 100*time.Millisecond)

util.SetupSignalHandler(done, func() {
sched.CancelJobsBlock()
cancelStop()
<-ctx.Done()
})

composeInstance, err := parser.GetCompose()
if err != nil {
logrus.Fatal(err)
}

c := client.Get()
if !c.HasValidSession() {
logrus.Fatal("no valid session, log in and try again")
}

go sched.Start()
defer cancelScheduler()

s.Color("blue")
s.Start()
defer s.Stop()

jobIDs := make(map[string]string)

c.DropDeploymentsCache()
depls, err := c.Deployments()
if err != nil {
logrus.Fatal(err)
}

deploymentMap := make(map[string]*body.DeploymentRead)
for _, depl := range depls {
deploymentMap[depl.Name] = &depl
}

for name := range composeInstance.Services {
if deployment, exists := deploymentMap[name]; exists {
sjob := scheduler.NewJob(func(ctx context.Context, cancelCallback func()) error {
disableDepl := &body.DeploymentUpdate{
Replicas: util.IntPointer(0),
}
resp, err := c.Update(disableDepl, deployment.ID)
if err != nil {
logrus.Error(err)
return err
}
err = response.IsError(resp.String())
if err != nil {
logrus.Error(err)
return err
}
job, err := util.ProcessResponse[body.DeploymentUpdated](resp.String())
if err != nil {
logrus.Error(err)
return err
}
return jobs.From(job).Track(ctx, deployment.Name, time.Millisecond*500, cancelCallback)
}, func() {})
jobIDs[name] = sched.AddJob(sjob)
}
}

if err := jobs.MonitorJobStates(jobIDs, sched, s); err != nil {
logrus.Debugln("erroccurred")
s.Color("red")
} else {
logrus.Debugln("alldone")
s.Color("green")
}
}
Loading

0 comments on commit 20c2880

Please sign in to comment.