Skip to content

Commit

Permalink
lint works
Browse files Browse the repository at this point in the history
  • Loading branch information
dazz committed Dec 26, 2023
1 parent db37980 commit cf55d24
Show file tree
Hide file tree
Showing 12 changed files with 305 additions and 6 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# s6-cli: A cli for s6-overlay

todo
* write tests with https://github.com/stretchr/testify
* style output with color https://github.com/charmbracelet/glamour
29 changes: 25 additions & 4 deletions cmd/s6cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package main

import (
"fmt"
"github.com/dazz/s6-cli/internal/domain/lint"
"github.com/dazz/s6-cli/internal/infrastructure/persistence"
"log"
"os"
"time"
Expand All @@ -20,7 +22,7 @@ func main() {
Version: "0.0.1",
Compiled: time.Now(),
Authors: []*cli.Author{
&cli.Author{
{
Name: "Anne-Julia Seitz",
Email: "dazz@c-base",
},
Expand All @@ -30,13 +32,32 @@ func main() {
// so we'll define it up here
Flags: []cli.Flag{
&cli.StringFlag{
Name: "path",
Name: "rootPath",
Aliases: []string{"p"},
Value: "/etc/s6-overlay/s6-rc.d",
Usage: "Path to s6-rc.d directory",
},
},
Commands: []*cli.Command{
{
Name: "lint-new",
Aliases: []string{"ll"},
Usage: "lint directories and files",
Action: func(cCtx *cli.Context) error {
rootPath := "/etc/s6-overlay/s6-rc.d"

if cCtx.IsSet("rootPath") {
rootPath = cCtx.String("rootPath")
}

repo := persistence.NewFilesystem(rootPath)
action := lint.NewAction(repo)

action.Lint()

return nil
},
},
{
Name: "lint",
Aliases: []string{"l"},
Expand All @@ -62,8 +83,8 @@ func main() {
fmt.Println("*************** s6-cli Lint Report ***************")

// print lints
for _, lint := range lints {
fmt.Printf("* %s: %s\n", lint.Service, lint.Message)
for _, l := range lints {
fmt.Printf("* %s: %s\n", l.Service, l.Message)
}

fmt.Println("*************** s6-cli Lint Report ***************")
Expand Down
3 changes: 3 additions & 0 deletions examples/s6-overlay/s6-rc.d/missing-dependency-dir/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/command/execlineb -P

echo "Hello, world!"
1 change: 1 addition & 0 deletions examples/s6-overlay/s6-rc.d/missing-dependency-dir/type
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
longrun
Empty file.
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ go 1.20

require (
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/stretchr/testify v1.8.4 // indirect
github.com/urfave/cli/v2 v2.26.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
17 changes: 17 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,26 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHH
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI=
github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
33 changes: 33 additions & 0 deletions internal/domain/lint/action.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package lint

import (
"fmt"
"github.com/dazz/s6-cli/internal/domain/service"
"log"
)

type Action struct {
repository service.Repository
}

func NewAction(repository service.Repository) *Action {
return &Action{
repository: repository,
}
}

func (a *Action) Lint() bool {
// do all the fun stuff here
services, err := a.repository.All()
if err != nil {
log.Println(err)
}

for _, s := range services {
fmt.Println("* " + s.Id)
for _, l := range s.Lints {
fmt.Println(" * " + l)
}
}
return false
}
7 changes: 7 additions & 0 deletions internal/domain/service/repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package service

type Repository interface {
All() ([]*Service, error)
//Create(service Service) error
//Remove(id Id) error
}
52 changes: 52 additions & 0 deletions internal/domain/service/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package service

import (
"errors"
)

const (
TypeOneshot Type = "oneshot"
TypeLongrun Type = "longrun"
TypeBundle Type = "bundle"
)

type Id string
type Type string
type Lint string

type Service struct {
Id Id
Type Type
Dependencies []Id
Lints []Lint
Valid bool
Path string
}

func NewService(id Id, rootPath string) *Service {
return &Service{
Id: id,
Path: rootPath + "/" + string(id),
Valid: true,
Lints: []Lint{},
}
}

func (s *Service) AddLint(lint string) {
s.Lints = append(s.Lints, Lint(lint))
s.Valid = false
}

func (s *Service) DependencyDir() (string, error) {
if s.Type == TypeBundle {
return s.Path + "/contents.d", nil
}
if s.Type == TypeOneshot || s.Type == TypeLongrun {
return s.Path + "/dependencies.d", nil
}
return "", errors.New("invalid service type")
}

func (s *Service) AddDependency(dependency string) {
s.Dependencies = append(s.Dependencies, Id(dependency))
}
156 changes: 156 additions & 0 deletions internal/infrastructure/persistence/filesystem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package persistence

import (
"errors"
"fmt"
"github.com/dazz/s6-cli/internal/domain/service"
"log"
"os"
"strings"
)

const RootService service.Id = "user"

type Filesystem struct {
rootPath string
byId map[service.Id]*service.Service
allIds []service.Id
}

func NewFilesystem(rootPath string) *Filesystem {
return &Filesystem{
rootPath: rootPath,
byId: make(map[service.Id]*service.Service),
allIds: []service.Id{},
}
}

func (fs *Filesystem) All() ([]*service.Service, error) {
err := fs.compile(RootService)
if err != nil {
log.Println(err)
}
var services []*service.Service
for _, id := range fs.allIds {
services = append(services, fs.byId[id])
//fmt.Println(id)
}
return services, nil
}

func (fs *Filesystem) contains(id service.Id) bool {
_, ok := fs.byId[id]
if ok {
return true
}
return false
}

// compile all folders and directories to a list of services we can work with
func (fs *Filesystem) compile(id service.Id) error {
if id == "" {
id = RootService
}

// Check if the service is already in the services list
if fs.contains(id) {
return nil
}

s := service.NewService(id, fs.rootPath)

// add the service to the services list
fs.byId[id] = s
fs.allIds = append(fs.allIds, id)

// Check if the directory exists
if _, err := os.Stat(s.Path); os.IsNotExist(err) {
s.AddLint(fmt.Sprintf("invalid directory: path %s does not exist", s.Path))
return nil
}

serviceType, err := fs.serviceType(s)
if err != nil {
s.AddLint(err.Error())
return nil
}
s.Type = serviceType

// check if the run file exists
if serviceType == service.TypeLongrun {
runFile := s.Path + "/run"
if _, err := os.Stat(runFile); os.IsNotExist(err) {
s.AddLint("run file for longrun does not exist")
}
}

// check if the up file exists
if serviceType == "oneshot" {
upFile := s.Path + "/up"
if _, err := os.Stat(upFile); os.IsNotExist(err) {
s.AddLint("up file for oneshot does not exist")
}
}

// check if the dependency directory exists
dependencyDir, err := s.DependencyDir()
if err != nil {
s.AddLint(fmt.Sprintf("service type (%s) in type file for %s does not exist", serviceType, id))
}

// get the dependencies
files, err := os.ReadDir(dependencyDir)
if err != nil {
s.AddLint("service has no dependency directory")
return nil
}
for _, file := range files {
if file.Name() == "base" {
// we don't want to check the base directory
continue
}
s.AddDependency(file.Name())
}

for _, dependency := range s.Dependencies {
if fs.contains(dependency) || dependency == "base" {
continue
}
// recursive call
err := fs.compile(dependency)
if err != nil {
s.AddLint(fmt.Sprintf("dependency error: %s", err))
}
}

return nil
}

func (fs *Filesystem) serviceType(s *service.Service) (service.Type, error) {
// check the type file and content
typeFileContent, err := os.ReadFile(s.Path + "/type")
if err != nil {
s.AddLint(fmt.Sprintf("type file for \"%s\" does not exist", s.Id))
return "", err
}
// Check if the file is empty
if len(typeFileContent) == 0 {
s.AddLint(fmt.Sprintf("type file for \"%s\" is empty", s.Id))
return "", err
}

// Check if the last character is a newline
lastChar := typeFileContent[len(typeFileContent)-1]
if lastChar != '\n' {
s.AddLint(fmt.Sprintf("type file for \"%s\" does not end with a newline", s.Id))
}

serviceType := service.Type(strings.ReplaceAll(string(typeFileContent), "\n", ""))
for _, theType := range []service.Type{service.TypeOneshot, service.TypeLongrun, service.TypeBundle} {
if serviceType == theType {
return serviceType, nil
}
}

return "", errors.New(fmt.Sprintf("invalid type in %s/type file specified", s.Id))
}
3 changes: 1 addition & 2 deletions pkg/s6cli/lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package s6cli

import (
"fmt"
"io/ioutil"
"log"
"os"
"strings"
Expand Down Expand Up @@ -109,7 +108,7 @@ func Compile(rootPath string, serviceName string, services *[]Service, lints *[]
}

// get the dependencies
files, err := ioutil.ReadDir(dependenciesDir)
files, err := os.ReadDir(dependenciesDir)
if err != nil {
log.Fatal(err)
}
Expand Down

0 comments on commit cf55d24

Please sign in to comment.