Skip to content

Commit

Permalink
Improvements:
Browse files Browse the repository at this point in the history
- Reorder service name inference
- Add service name infrerence to ecs
- Upgrade pterm and go
- Add spinner to logs
- Logs: reorder log stream prefix inference
- ECS deployment: add debug task definition logs, improve messages
- ize.toml in the directory is considered a valid ize directory (no warning)
- Handle case when there is no terraform infra in the ize.toml
- Update Status message language
  • Loading branch information
AutomationD committed May 14, 2024
1 parent 8b7a565 commit d16bfde
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 36 deletions.
35 changes: 19 additions & 16 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module github.com/hazelops/ize

go 1.18
go 1.21

toolchain go1.22.2

require (
github.com/AlecAivazis/survey/v2 v2.3.4
Expand Down Expand Up @@ -28,26 +30,27 @@ require (
github.com/olekukonko/tablewriter v0.0.5
github.com/psihachina/path-parser v1.0.1
github.com/psihachina/terraform-switcher v0.13.1275
github.com/pterm/pterm v0.12.49
github.com/pterm/pterm v0.12.79
github.com/santhosh-tekuri/jsonschema v1.2.4
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.4.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.12.0
github.com/stretchr/testify v1.8.0
github.com/stretchr/testify v1.8.4
github.com/xeipuuv/gojsonschema v1.2.0
github.com/zclconf/go-cty v1.10.0
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
golang.org/x/text v0.3.7
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561
golang.org/x/sync v0.1.0
golang.org/x/term v0.16.0
golang.org/x/text v0.14.0
gopkg.in/ini.v1 v1.66.6
)

require (
atomicgo.dev/cursor v0.1.1 // indirect
atomicgo.dev/keyboard v0.2.8 // indirect
atomicgo.dev/cursor v0.2.0 // indirect
atomicgo.dev/keyboard v0.2.9 // indirect
atomicgo.dev/schedule v0.1.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/Microsoft/hcsshim v0.9.2 // indirect
Expand All @@ -71,7 +74,7 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/gookit/color v1.5.2 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/hashicorp/go-hclog v1.2.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect
Expand All @@ -82,10 +85,10 @@ require (
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/lithammer/fuzzysearch v1.1.5 // indirect
github.com/lithammer/fuzzysearch v1.1.8 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
Expand All @@ -102,7 +105,7 @@ require (
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.6.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
Expand All @@ -114,11 +117,11 @@ require (
github.com/xanzy/ssh-agent v0.3.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
github.com/y0ssar1an/q v1.0.7 // indirect
go.opencensus.io v0.23.0 // indirect
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 // indirect
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
golang.org/x/net v0.6.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
43 changes: 43 additions & 0 deletions go.sum

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions internal/commands/console.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,19 +213,21 @@ func (o *ConsoleOptions) Run() error {
func getEcsServiceName(o *ConsoleOptions) (string, error) {
// TODO: Move core logic to a shared function (since it's used in deploy too)
ecsServiceCandidates := []string{
o.AppName,
fmt.Sprintf("%s-%s", o.Config.Env, o.AppName),
fmt.Sprintf("%s-%s-%s", o.Config.Env, o.Config.Namespace, o.AppName),
fmt.Sprintf("%s-%s", o.Config.Env, o.AppName),
o.AppName,
}

for _, v := range ecsServiceCandidates {
// Searching for a service that has running tasks
logrus.Debugf("Checking if ECS service %s exists in cluster %s.", v, o.EcsCluster)
_, err := o.Config.AWSClient.ECSClient.ListTasks(&ecs.ListTasksInput{
Cluster: &o.EcsCluster,
DesiredStatus: aws.String(ecs.DesiredStatusRunning),
ServiceName: &v,
})

// If during the search we encounter exceptions, handle them.
var aerr awserr.Error
if errors.As(err, &aerr) {
switch aerr.Code() {
Expand Down
14 changes: 9 additions & 5 deletions internal/commands/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package commands
import (
"errors"
"fmt"
"github.com/pterm/pterm"
"os"
"strings"
"time"
Expand Down Expand Up @@ -86,6 +87,7 @@ func (o *LogsOptions) Validate() error {

func (o *LogsOptions) Run() error {
var err error
s, _ := pterm.DefaultSpinner.WithRemoveWhenDone().Start("Getting access to logs...")

if len(o.LogGroupName) == 0 {
o.LogGroupName, err = getEcsServiceLogGroupName(o)
Expand Down Expand Up @@ -124,6 +126,8 @@ func (o *LogsOptions) Run() error {
o.LogStreamName = fmt.Sprintf("%s/%s", logStreamPrefix, taskID)
}

s.Success()

GetLogs(o.Config.AWSClient.CloudWatchLogsClient, o.LogGroupName, o.LogStreamName, token)

return nil
Expand Down Expand Up @@ -169,9 +173,9 @@ func formatMessage(e *cloudwatchlogs.OutputLogEvent) (t time.Time, m string) {
func getEcsServiceLogGroupName(o *LogsOptions) (string, error) {
// TODO: Move core logic to a shared function (since it's used in deploy too)
ecsServiceLogGroupCandidates := []string{
o.AppName,
fmt.Sprintf("%s-%s", o.Config.Env, o.AppName),
fmt.Sprintf("%s-%s-%s", o.Config.Env, o.Config.Namespace, o.AppName),
fmt.Sprintf("%s-%s", o.Config.Env, o.AppName),
o.AppName,
}

for _, v := range ecsServiceLogGroupCandidates {
Expand Down Expand Up @@ -201,10 +205,10 @@ func getEcsServiceLogGroupName(o *LogsOptions) (string, error) {

func getEcsServiceLogStreamPrefix(o *LogsOptions) (string, error) {
ecsServiceLogStreamNameCandidates := []string{
o.AppName,
fmt.Sprintf("main/%s-%s", o.Config.Namespace, o.AppName),
fmt.Sprintf("main/%s-%s", o.Config.Env, o.AppName),
fmt.Sprintf("main/%s-%s-%s", o.Config.Env, o.Config.Namespace, o.AppName),
fmt.Sprintf("main/%s-%s", o.Config.Env, o.AppName),
fmt.Sprintf("main/%s-%s", o.Config.Namespace, o.AppName),
o.AppName,
}

for _, v := range ecsServiceLogStreamNameCandidates {
Expand Down
19 changes: 13 additions & 6 deletions internal/commands/up_apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package commands

import (
"context"
"errors"
"fmt"

"github.com/aws/aws-sdk-go/aws"
Expand Down Expand Up @@ -103,9 +104,16 @@ func (o *UpAppsOptions) Run() error {
ui.Output("Deploying apps...", terminal.WithHeaderStyle())

err := manager.InDependencyOrder(aws.BackgroundContext(), o.Config.GetApps(), func(c context.Context, name string) error {
o.Config.AwsProfile = o.Config.Terraform["infra"].AwsProfile
var err error
if len(o.Config.AwsProfile) == 0 {
if v, exists := o.Config.Terraform["infra"]; exists {
o.Config.AwsProfile = v.AwsProfile
} else {
err = errors.New("can't detect aws_profile. Please set it via env var (AWS_PROFILE) or in ize.toml")
}
}

err := deployApp(name, ui, o.Config, false)
err = deployApp(name, ui, o.Config, false)
if err != nil {
return err
}
Expand All @@ -116,7 +124,7 @@ func (o *UpAppsOptions) Run() error {
return err
}

ui.Output("Deploy all completed!\n", terminal.WithSuccessStyle())
ui.Output("Deploy complete!\n", terminal.WithSuccessStyle())

return nil
}
Expand Down Expand Up @@ -160,7 +168,7 @@ func deployApp(name string, ui terminal.UI, cfg *config.Project, isExplain bool)
icon += " "
}

ui.Output("Deploying %s%s app...", icon, name, terminal.WithHeaderStyle())
ui.Output("%s%s: bringing up...", icon, name, terminal.WithHeaderStyle())

// build app container
err := m.Build(ui)
Expand All @@ -180,8 +188,7 @@ func deployApp(name string, ui terminal.UI, cfg *config.Project, isExplain bool)
return fmt.Errorf("can't deploy app: %w", err)
}

ui.Output("Deploy app %s%s completed\n", icon, name, terminal.WithSuccessStyle())
ui.Output("%s%s: done.\n", icon, name, terminal.WithSuccessStyle())

return nil
}

58 changes: 52 additions & 6 deletions internal/manager/ecs/ecs.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"context"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"github.com/aws/aws-sdk-go/aws/awserr"
"os"
"path"
"path/filepath"
Expand Down Expand Up @@ -61,7 +63,11 @@ func (e *Manager) prepare() {
}

if len(e.App.ServiceName) == 0 {
e.App.ServiceName = fmt.Sprintf("%s-%s", e.Project.Env, e.App.Name)
var err error
e.App.ServiceName, err = getEcsServiceName(e)
if err != nil {

}
}
}

Expand Down Expand Up @@ -101,7 +107,7 @@ func (e *Manager) Deploy(ui terminal.UI) error {
- Unhealthy Threshold Count: 2`))
}

s := sg.Add("%s: deploying app container...", e.App.Name)
s := sg.Add("%s: deploying to ECS %s", e.App.Name, e.App.ServiceName)
defer func() { s.Abort(); time.Sleep(50 * time.Millisecond) }()

if e.App.Image == "" {
Expand Down Expand Up @@ -151,7 +157,7 @@ func (e *Manager) Redeploy(ui terminal.UI) error {
e.Project.SettingAWSClient(sess)
}

s := sg.Add("%s: redeploying app container...", e.App.Name)
s := sg.Add("%s: redeploying to ECS %s", e.App.Name, e.App.ServiceName)
defer func() { s.Abort(); time.Sleep(50 * time.Millisecond) }()

if e.Project.PreferRuntime == "native" {
Expand Down Expand Up @@ -180,7 +186,7 @@ func (e *Manager) Push(ui terminal.UI) error {
sg := ui.StepGroup()
defer sg.Wait()

s := sg.Add("%s: push app image...", e.App.Name)
s := sg.Add("%s: pushing app image...", e.App.Name)
defer func() { s.Abort(); time.Sleep(50 * time.Millisecond) }()

if len(e.App.Image) != 0 {
Expand Down Expand Up @@ -268,11 +274,11 @@ func (e *Manager) Build(ui terminal.UI) error {
sg := ui.StepGroup()
defer sg.Wait()

s := sg.Add("%s: building app container...", e.App.Name)
s := sg.Add("%s: building docker image...", e.App.Name)
defer func() { s.Abort(); time.Sleep(50 * time.Millisecond) }()

if len(e.App.Image) != 0 {
s.Update("%s: building app container... (skipped, using %s)", e.App.Name, e.App.Image)
s.Update("%s: building docker image... (skipped, using %s)", e.App.Name, e.App.Image)

s.Done()
return nil
Expand Down Expand Up @@ -388,3 +394,43 @@ func (e *Manager) Destroy(ui terminal.UI, autoApprove bool) error {

return nil
}

func getEcsServiceName(e *Manager) (string, error) {
// TODO: Move core logic to a shared function (since it's used in deploy too)
ecsServiceCandidates := []string{
fmt.Sprintf("%s-%s-%s", e.Project.Env, e.Project.Namespace, e.App.Name),
fmt.Sprintf("%s-%s", e.Project.Env, e.App.Name),
e.App.Name,
}

for _, v := range ecsServiceCandidates {
logrus.Debugf("Checking if ECS service %s exists in cluster %s.", v, e.App.Cluster)

_, err := e.Project.AWSClient.ECSClient.ListTasks(&ecs.ListTasksInput{
Cluster: &e.App.Cluster,
DesiredStatus: aws.String(ecs.DesiredStatusRunning),
ServiceName: &v,
})

var aerr awserr.Error
if errors.As(err, &aerr) {
switch aerr.Code() {
case "ClusterNotFoundException":
return "", fmt.Errorf("ECS cluster %s not found", e.App.Cluster)
case "ServiceNotFoundException":
{
logrus.Infof("ECS Service not found: %s in cluster %s. Checking other options.", v, e.App.Cluster)
continue
}
default:
{
return "", err
}
}

}
return v, err
}
err := errors.New("ECS Service not found")
return "", err
}
19 changes: 18 additions & 1 deletion internal/manager/ecs/native.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package ecs

import (
"encoding/json"
"fmt"
"github.com/sirupsen/logrus"
"io"
"strconv"
"strings"
Expand Down Expand Up @@ -64,6 +66,12 @@ func (e *Manager) deployLocal(w io.Writer) error {
oldTaskDef = *dtdo.TaskDefinition
}

oldTaskDefJson, err := json.Marshal(oldTaskDef)
if err != nil {
return err
}

logrus.Debugf("oldTaskDef: %s", string(oldTaskDefJson))
pterm.Printfln("Deploying based on task definition: %s:%d", *oldTaskDef.Family, *oldTaskDef.Revision)

var image string
Expand Down Expand Up @@ -105,6 +113,12 @@ func (e *Manager) deployLocal(w io.Writer) error {

newTaskDef = *rtdo.TaskDefinition

newTaskDefJson, err := json.Marshal(newTaskDef)
if err != nil {
return err
}

logrus.Debugf("newTaskDef: %s", string(newTaskDefJson))
pterm.Printfln("Successfully created revision: %s:%d", *rtdo.TaskDefinition.Family, *rtdo.TaskDefinition.Revision)

if err = e.updateTaskDefinition(&newTaskDef, &oldTaskDef, e.App.ServiceName, "Deploying new task definition"); err != nil {
Expand All @@ -121,7 +135,10 @@ func (e *Manager) deployLocal(w io.Writer) error {
pterm.Printfln("Container %s couldn't start: %s", e.App.ServiceName, sr)

pterm.Printfln("Rolling back to old task definition: %s:%d", *oldTaskDef.Family, *oldTaskDef.Revision)

e.App.Timeout = 600
logrus.Debugf("Setting timeout to %d seconds", e.App.Timeout)

if err = e.updateTaskDefinition(&oldTaskDef, &newTaskDef, e.App.ServiceName, "Deploying previous task definition"); err != nil {
return fmt.Errorf("unable to rollback to old task definition: %w", err)
}
Expand Down Expand Up @@ -221,7 +238,7 @@ func getService(name string, cluster string, svc ecsiface.ECSAPI) (*ecs.Describe
}

func (e *Manager) updateTaskDefinition(newTD *ecs.TaskDefinition, oldTD *ecs.TaskDefinition, serviceName string, title string) error {
pterm.Println("Updating service")
pterm.Printfln("Updating ECS service: %s (timeout: %d)", e.App.ServiceName, e.App.Timeout)

svc := e.Project.AWSClient.ECSClient

Expand Down
5 changes: 5 additions & 0 deletions internal/requirements/requirements.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ func isStructured() bool {
isStructured = true
}

_, err = os.Stat(filepath.Join(cwd, "ize.toml"))
if !os.IsNotExist(err) {
isStructured = true
}

return isStructured
}

Expand Down

0 comments on commit d16bfde

Please sign in to comment.