WIP - there still are problem with several things

- ports label are not well managed
- no heathcheck, have to be rewritten
- many problem with generated compose file from memory
This commit is contained in:
2022-04-04 09:53:36 +02:00
parent cc73d57f5a
commit e346bb3ae4
6 changed files with 87 additions and 156 deletions

View File

@@ -11,9 +11,6 @@ import (
"strconv"
"strings"
"sync"
"time"
"errors"
"github.com/compose-spec/compose-go/types"
)
@@ -123,33 +120,6 @@ func parseService(name string, s types.ServiceConfig, linked map[string]types.Se
}
}
// Special case, it there is no "ports", so there is no associated services...
// But... some other deployment can wait for it, so we alert that this deployment hasn't got any
// associated service.
if len(s.Ports) == 0 {
// alert any current or **future** waiters that this service is not exposed
go func() {
defer func() {
// recover from panic
if r := recover(); r != nil {
// log the stack trace
fmt.Println(r)
}
}()
for {
select {
case <-time.Tick(1 * time.Millisecond):
locker.Lock()
for _, c := range serviceWaiters[name] {
c <- -1
close(c)
}
locker.Unlock()
}
}
}()
}
// add the volumes in Values
if len(VolumeValues[name]) > 0 {
locker.Lock()
@@ -166,6 +136,8 @@ func parseService(name string, s types.ServiceConfig, linked map[string]types.Se
// prepareContainer assigns image, command, env, and labels to a container.
func prepareContainer(container *helm.Container, service types.ServiceConfig, servicename string) {
locker.Lock()
defer locker.Unlock()
// if there is no image name, this should fail!
if service.Image == "" {
log.Fatal(ICON_PACKAGE+" No image name for service ", servicename)
@@ -186,11 +158,8 @@ func generateServicesAndIngresses(name string, s types.ServiceConfig) []interfac
logger.Magenta(ICON_SERVICE+" Generating service for ", name)
ks := helm.NewService(name)
for i, p := range s.Ports {
for _, p := range s.Ports {
ks.Spec.Ports = append(ks.Spec.Ports, helm.NewServicePort(int(p.Target), int(p.Target)))
if i == 0 {
detected(name, int(p.Target))
}
}
ks.Spec.Selector = buildSelector(name, s)
@@ -253,49 +222,6 @@ func createIngress(name string, port int, s types.ServiceConfig) *helm.Ingress {
return ingress
}
// This function is called when a possible service is detected, it append the port in a map to make others
// to be able to get the service name. It also try to send the data to any "waiter" for this service.
func detected(name string, port int) {
locker.Lock()
defer locker.Unlock()
if _, ok := servicesMap[name]; ok {
return
}
servicesMap[name] = port
go func() {
locker.Lock()
defer locker.Unlock()
if cx, ok := serviceWaiters[name]; ok {
for _, c := range cx {
c <- port
}
}
}()
}
func getPort(name string) (int, error) {
if v, ok := servicesMap[name]; ok {
return v, nil
}
return -1, errors.New("Not found")
}
// Waits for a service to be discovered. Sometimes, a deployment depends on another one. See the detected() function.
func waitPort(name string) chan int {
locker.Lock()
defer locker.Unlock()
c := make(chan int, 0)
serviceWaiters[name] = append(serviceWaiters[name], c)
go func() {
locker.Lock()
defer locker.Unlock()
if v, ok := servicesMap[name]; ok {
c <- v
}
}()
return c
}
// Build the selector for the service.
func buildSelector(name string, s types.ServiceConfig) map[string]string {
return map[string]string{
@@ -355,6 +281,20 @@ func generateContainerPorts(s types.ServiceConfig, name string, container *helm.
exists[int(port.Target)] = name
}
// Get ports from label
if v, ok := s.Labels[helm.LABEL_PORT]; ok {
// split port by ","
ports := strings.Split(v, ",")
for _, port := range ports {
port, _ := strconv.Atoi(port)
container.Ports = append(container.Ports, &helm.ContainerPort{
Name: name,
ContainerPort: port,
})
exists[port] = name
}
}
// manage the "expose" section to be a NodePort in Kubernetes
for _, expose := range s.Expose {
@@ -506,9 +446,11 @@ func prepareInitContainers(name string, s types.ServiceConfig, container *helm.C
command := strings.ReplaceAll(strings.TrimSpace(dependScript), "__service__", dp)
foundPort := -1
if defaultPort, err := getPort(dp); err != nil {
// BUG: Sometimes the chan remains opened
foundPort = <-waitPort(dp)
locker.Lock()
defer locker.Unlock()
if defaultPort, ok := servicesMap[dp]; !ok {
logger.Redf("Error while getting port for service %s\n", dp)
os.Exit(1)
} else {
foundPort = defaultPort
}

View File

@@ -5,10 +5,13 @@ import (
"katenary/compose"
"katenary/helm"
"katenary/logger"
"log"
"os"
"path/filepath"
"strings"
"testing"
"github.com/compose-spec/compose-go/cli"
)
const DOCKER_COMPOSE_YML = `version: '3'
@@ -92,17 +95,19 @@ volumes:
driver: local
`
var defaultCliFiles = cli.DefaultFileNames
func init() {
logger.NOLOG = true
}
func setUp(t *testing.T) (string, *compose.Parser) {
cli.DefaultFileNames = defaultCliFiles
p := compose.NewParser("", DOCKER_COMPOSE_YML)
p.Parse("testapp")
// create a temporary directory
tmp, err := os.MkdirTemp(os.TempDir(), "katenary-test")
t.Log("Generated ", tmp, "directory")
if err != nil {
t.Fatal(err)
}
@@ -115,7 +120,8 @@ func setUp(t *testing.T) (string, *compose.Parser) {
// Check if the web2 service has got a command.
func TestCommand(t *testing.T) {
tmp, p := setUp(t)
defer os.RemoveAll(tmp)
//defer os.RemoveAll(tmp)
log.Println(tmp)
for _, service := range p.Data.Services {
name := service.Name
@@ -138,6 +144,7 @@ func TestCommand(t *testing.T) {
commands = append(commands, line)
}
}
//log.Printf("%#v\n", commands)
ok := 0
for _, command := range commands {
if strings.Contains(command, "- /bin/sh") {
@@ -242,7 +249,7 @@ func TestPorts(t *testing.T) {
t.Log("Checking ", name, " service file")
_, err := os.Stat(path)
if err != nil {
t.Fatal(err)
t.Error(err)
}
}
}

View File

@@ -4,6 +4,7 @@ import (
"katenary/compose"
"katenary/generator/writers"
"katenary/helm"
"log"
"os"
"path/filepath"
"regexp"
@@ -26,33 +27,38 @@ func Generate(p *compose.Parser, katernayVersion, appName, appVersion, composeFi
// try to create the directory
err := os.MkdirAll(templatesDir, 0755)
if err != nil {
panic(err)
log.Fatal(err)
}
files := make(map[string]chan interface{})
// list avoided services
// Manage services, avoid linked pods and store all services port in servicesMap
avoids := make(map[string]bool)
linked := make(map[string]types.ServiceConfig, 0)
for _, service := range p.Data.Services {
n := service.Name
// find port and store it in servicesMap
for _, port := range service.Ports {
target := int(port.Target)
if target != 0 {
servicesMap[n] = target
}
}
// avoid linked pods
if _, ok := service.Labels[helm.LABEL_SAMEPOD]; ok {
avoids[n] = true
}
}
for _, s := range p.Data.Services {
name := s.Name
// Manage emptyDir volumes
if empty, ok := s.Labels[helm.LABEL_EMPTYDIRS]; ok {
// manage emptyDir volumes
if empty, ok := service.Labels[helm.LABEL_EMPTYDIRS]; ok {
//split empty list by coma
emptyDirs := strings.Split(empty, ",")
//append them in EmptyDirs
EmptyDirs = append(EmptyDirs, emptyDirs...)
}
// fetch corresponding service in "links"
linked := make(map[string]types.ServiceConfig, 0)
// find service linked to this one
for _, service := range p.Data.Services {
n := service.Name
@@ -62,6 +68,11 @@ func Generate(p *compose.Parser, katernayVersion, appName, appVersion, composeFi
}
}
}
}
// for all services in linked map, and not in avoids map, generate the service
for _, s := range p.Data.Services {
name := s.Name
if _, found := avoids[name]; found {
continue