commit 4e25a50bc48fa429db1804c5859380d359cff575 Author: jake Date: Sun Nov 9 11:06:04 2025 -0500 init commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..577ffa6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +compose.yaml \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..ce8ec35 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module code.jakeyoungdev.com/go/compose-parser + +go 1.24.6 + +require gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a62c313 --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go new file mode 100644 index 0000000..09db35d --- /dev/null +++ b/main.go @@ -0,0 +1,106 @@ +package main + +import ( + "fmt" + "io" + "os" + "regexp" + + "gopkg.in/yaml.v3" +) + +type RestartConfig struct { + Condition *string `yaml:"condition"` + Delay *string `yaml:"delay"` + MaxAttempts *int `yaml:"max_attempts"` + Window *string `yaml:"window"` +} + +type DeployConfig struct { + Policy *RestartConfig `yaml:"restart_policy"` +} + +type ServiceConfig struct { + MemLimit *string `yaml:"mem_limit"` + Cpus *float64 `yaml:"cpus"` + Ports *[]string `yaml:"ports"` + Deploy *DeployConfig `yaml:"deploy"` +} + +type Compose struct { + Services map[string]ServiceConfig `yaml:"services"` +} + +func main() { + filePath := os.Getenv("COMPOSE_FILE_PATH") + if filePath == "" { + filePath = "./compose.yaml" + } + f, err := os.Open(filePath) + if err != nil { + panic(err) + } + defer f.Close() + + fd, err := io.ReadAll(f) + if err != nil { + panic(err) + } + + var data Compose + err = yaml.Unmarshal(fd, &data) + if err != nil { + panic(err) + } + + type report struct { + Name string + PolicyPresent bool + PortSafety bool + PortIssues []string + ResourceSafety bool + ResourceIssues []string + } + + var issues []report + for name, serviceConf := range data.Services { + r := report{ + Name: name, + } + + if serviceConf.Ports != nil { + matched, err := regexp.Match(`.*:.*:.*`, []byte((*serviceConf.Ports)[0])) + if err != nil { + panic(err) + } + + if !matched { + r.PortSafety = false + r.PortIssues = append(r.PortIssues, "host port does not have an IP addressed and is fully opened") + } else { + r.PortSafety = true + } + } else { + r.PortSafety = true + } + + r.ResourceSafety = true + if serviceConf.MemLimit == nil { + r.ResourceSafety = false + r.ResourceIssues = append(r.ResourceIssues, "no memory limit set") + } + if serviceConf.Cpus == nil { + r.ResourceSafety = false + r.ResourceIssues = append(r.ResourceIssues, "no cpu limit set") + } + + if serviceConf.Deploy != nil && serviceConf.Deploy.Policy != nil { + r.PolicyPresent = true + } else { + r.PolicyPresent = false + } + + fmt.Printf("%+v\n", r) + issues = append(issues, r) + } +}