abra/cli/recipe/lint.go

114 lines
3.0 KiB
Go
Raw Normal View History

2021-09-05 20:33:07 +00:00
package recipe
import (
"fmt"
"os"
"strconv"
"coopcloud.tech/abra/cli/formatter"
"coopcloud.tech/abra/cli/internal"
"coopcloud.tech/abra/pkg/catalogue"
2021-09-05 20:33:07 +00:00
"coopcloud.tech/abra/pkg/config"
"coopcloud.tech/tagcmp"
"github.com/docker/distribution/reference"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
)
var recipeLintCommand = &cli.Command{
Name: "lint",
Usage: "Lint a recipe",
Aliases: []string{"l"},
ArgsUsage: "<recipe>",
Action: func(c *cli.Context) error {
2021-09-05 23:43:21 +00:00
recipe := internal.ValidateRecipe(c)
2021-09-05 20:33:07 +00:00
expectedVersion := false
2021-09-05 23:43:21 +00:00
if recipe.Config.Version == "3.8" {
2021-09-05 20:33:07 +00:00
expectedVersion = true
}
envSampleProvided := false
2021-09-05 23:43:21 +00:00
envSample := fmt.Sprintf("%s/%s/.env.sample", config.APPS_DIR, recipe.Name)
2021-09-05 20:33:07 +00:00
if _, err := os.Stat(envSample); !os.IsNotExist(err) {
envSampleProvided = true
2021-09-05 23:43:21 +00:00
} else if err != nil {
2021-09-05 20:33:07 +00:00
logrus.Fatal(err)
}
serviceNamedApp := false
traefikEnabled := false
healthChecksForAllServices := true
allImagesTagged := true
noUnstableTags := true
semverLikeTags := true
2021-09-05 23:43:21 +00:00
for _, service := range recipe.Config.Services {
2021-09-05 20:33:07 +00:00
if service.Name == "app" {
serviceNamedApp = true
}
for label := range service.Deploy.Labels {
if label == "traefik.enable" {
if service.Deploy.Labels[label] == "true" {
traefikEnabled = true
}
}
}
img, err := reference.ParseNormalizedNamed(service.Image)
if err != nil {
logrus.Fatal(err)
}
if reference.IsNameOnly(img) {
allImagesTagged = false
}
var tag string
switch img.(type) {
case reference.NamedTagged:
tag = img.(reference.NamedTagged).Tag()
case reference.Named:
noUnstableTags = false
}
2021-09-05 20:33:07 +00:00
if tag == "latest" {
noUnstableTags = false
}
if !tagcmp.IsParsable(tag) {
semverLikeTags = false
}
if service.HealthCheck == nil {
healthChecksForAllServices = false
}
}
tableCol := []string{"rule", "satisfied"}
2021-09-05 20:33:07 +00:00
table := formatter.CreateTable(tableCol)
table.Append([]string{"compose files have the expected version", strconv.FormatBool(expectedVersion)})
table.Append([]string{"environment configuration is provided", strconv.FormatBool(envSampleProvided)})
table.Append([]string{"recipe contains a service named 'app'", strconv.FormatBool(serviceNamedApp)})
table.Append([]string{"traefik routing enabled on at least one service", strconv.FormatBool(traefikEnabled)})
table.Append([]string{"all services have a healthcheck enabled", strconv.FormatBool(healthChecksForAllServices)})
table.Append([]string{"all images are using a tag", strconv.FormatBool(allImagesTagged)})
table.Append([]string{"no usage of unstable 'latest' tags", strconv.FormatBool(noUnstableTags)})
table.Append([]string{"all tags are using a semver-like format", strconv.FormatBool(semverLikeTags)})
2021-09-05 20:33:07 +00:00
table.Render()
return nil
},
BashComplete: func(c *cli.Context) {
catl, err := catalogue.ReadRecipeCatalogue()
if err != nil {
logrus.Warn(err)
}
if c.NArg() > 0 {
return
}
2021-09-16 11:01:47 +00:00
for name := range catl {
fmt.Println(name)
}
},
2021-09-05 20:33:07 +00:00
}