Refactor service deployment loading logic

This commit is contained in:
Milos Pejanovic
2020-03-03 15:23:10 +01:00
parent 657b0c2369
commit 8ef2d75fcb
3 changed files with 143 additions and 51 deletions
+5 -5
View File
@@ -28,14 +28,14 @@ var (
)
func Deploy(namespace, deployment, tag string) {
sds, err := cnf.ServiceDeployments(cwdir, namespace, deployment)
if err != nil {
log.Fatalf("could not deploy: %v output:\n%v", deployment, err)
sds := cnf.GetServiceDeployments(namespace, deployment)
if len(sds) == 0 {
log.Fatalf("could not find any service deployments for namespace: %v and deployment: %v", namespace, deployment)
}
if flagBuild {
for _, serviceDeployment := range sds {
Build(serviceDeployment.ServiceName, FlagTag)
Build(serviceDeployment.ServiceName, tag)
}
}
cnf.Deploy(sds, cwdir, tag)
cnf.Deploy(sds, cwdir)
}
+111 -1
View File
@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"io"
"log"
"os"
"path"
"path/filepath"
@@ -25,10 +26,20 @@ var (
ErrServiceNotFound = errors.New("service not found")
)
type Deployment struct {
name string
serviceDeployments []ServiceDeployment
}
type Namespace struct {
name string
deployments []Deployment
}
type Configurd struct {
Services []Service
Templates []string
Namespaces []string
Namespaces []Namespace
}
func New(dir string) (Configurd, error) {
@@ -59,9 +70,88 @@ func New(dir string) (Configurd, error) {
return Configurd{}, err
}
c.Namespaces, err = loadNamespaces(c, dir)
if err != nil {
return Configurd{}, err
}
return c, nil
}
func loadNamespaces(c Configurd, basePath string) ([]Namespace, error) {
var nss []Namespace
namespaceDir := path.Join(basePath, defaultNamespaceDir)
err := filepath.Walk(namespaceDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() && path != namespaceDir {
ds, err := loadDeployments(c, info.Name())
if err != nil {
return err
}
ns := Namespace{
name: info.Name(),
deployments: ds,
}
nss = append(nss, ns)
}
return nil
})
return nss, err
}
func loadDeployments(c Configurd, namespace string) ([]Deployment, error) {
var ds []Deployment
err := filepath.Walk(path.Join(defaultNamespaceDir, namespace), func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && (strings.HasSuffix(path, defaultConfigFileExt)) {
var name = info.Name()[0 : len(info.Name())-len(filepath.Ext(info.Name()))]
sds, err := loadServiceDeployments(c, namespace, name)
if err != nil {
return err
}
d := Deployment{
name: name,
serviceDeployments: sds,
}
ds = append(ds, d)
}
return nil
})
return ds, err
}
func loadServiceDeployments(c Configurd, namespace, deployment string) ([]ServiceDeployment, error) {
path := path.Join(defaultNamespaceDir, namespace, deployment+defaultConfigFileExt)
file, err := os.Open(path)
defer file.Close()
if err != nil {
return []ServiceDeployment{}, err
}
var wrapper struct {
ServiceDeployments []ServiceDeployment `yaml:"services"`
}
if err := yaml.NewDecoder(file).Decode(&wrapper); err != nil {
return []ServiceDeployment{}, fmt.Errorf("could not decode service deployment: %w", err)
}
for i, sd := range wrapper.ServiceDeployments {
svc, err := c.Service(sd.ServiceName)
if err != nil {
log.Fatal(err)
}
wrapper.ServiceDeployments[i].chart = svc.Chart
wrapper.ServiceDeployments[i].namespace = namespace
wrapper.ServiceDeployments[i].deployment = deployment
}
return wrapper.ServiceDeployments, nil
}
func (c Configurd) Service(name string) (Service, error) {
for _, svc := range c.Services {
if svc.Name == name {
@@ -71,6 +161,26 @@ func (c Configurd) Service(name string) (Service, error) {
return Service{}, ErrServiceNotFound
}
func (c Configurd) GetServiceDeployments(namespace, deployment string) []ServiceDeployment {
var sds []ServiceDeployment
for _, sd := range c.serviceDeployments() {
if sd.namespace == namespace && sd.deployment == deployment {
sds = append(sds, sd)
}
}
return sds
}
func (c Configurd) serviceDeployments() []ServiceDeployment {
var sds []ServiceDeployment
for _, ns := range c.Namespaces {
for _, d := range ns.deployments {
sds = append(sds, d.serviceDeployments...)
}
}
return sds
}
func loadService(reader io.Reader) (Service, error) {
var wrapper struct {
Service Service `yaml:"service"`
+27 -45
View File
@@ -16,8 +16,9 @@ import (
type ServiceDeployment struct {
ServiceName string `yaml:"service"`
Overrides interface{}
chart string
namespace string
deployment string
chart string
}
func generateYaml(path string, data interface{}) error {
@@ -37,7 +38,7 @@ func generateYaml(path string, data interface{}) error {
return nil
}
func generate(sd ServiceDeployment, outputDir, chartPath, tag string) error {
func generate(sd ServiceDeployment, outputDir, chartPath string) error {
dir := path.Join(outputDir, sd.ServiceName)
if err := os.MkdirAll(dir, 0744); err != nil {
return fmt.Errorf("could not create output dir: %w", err)
@@ -69,7 +70,27 @@ func generate(sd ServiceDeployment, outputDir, chartPath, tag string) error {
return nil
}
func (c Configurd) Deploy(sds []ServiceDeployment, basePath, tag string) (string, error) {
func helmInstall(serviceName, namespace, basePath string) error {
chartPath := path.Join(basePath, defaultDeploymentDir, serviceName)
cmdArgs := []string{
"install", serviceName, chartPath,
"-f", path.Join(chartPath, defaultOverridesFile),
"-n", namespace,
"--set", "fullnameOverride=" + serviceName,
}
cmd := exec.Command("helm", cmdArgs...)
out, err := cmd.CombinedOutput()
output := strings.Replace(string(out), "\n", "\n\t", -1)
log.Print(string(out))
if err != nil {
return fmt.Errorf("could not install a helm chart for service %v output: \n%v", serviceName, output)
}
return nil
}
func (c Configurd) Deploy(sds []ServiceDeployment, basePath string) (string, error) {
if err := os.RemoveAll(defaultDeploymentDir); err != nil {
return "", fmt.Errorf("could not clean deployment directory: %w", err)
}
@@ -78,54 +99,15 @@ func (c Configurd) Deploy(sds []ServiceDeployment, basePath, tag string) (string
return "", fmt.Errorf("could not create a deployments directory: %w", err)
}
for _, sd := range sds {
err := generate(sd, defaultDeploymentDir, path.Join(defaultChartDir, sd.chart), tag)
err := generate(sd, defaultDeploymentDir, path.Join(defaultChartDir, sd.chart))
if err != nil {
return "", err
}
// helm install
chartPath := path.Join(basePath, defaultDeploymentDir, sd.ServiceName)
cmdArgs := []string{
"install", sd.ServiceName, chartPath,
"-f", path.Join(chartPath, defaultOverridesFile),
"-n", sd.namespace,
"--set", "fullnameOverride=" + sd.ServiceName,
}
cmd := exec.Command("helm", cmdArgs...)
out, err := cmd.CombinedOutput()
output := strings.Replace(string(out), "\n", "\n\t", -1)
log.Print(string(out))
err = helmInstall(sd.ServiceName, sd.namespace, basePath)
if err != nil {
return "", fmt.Errorf("could not install a helm chart for service %v output: \n%v", sd.ServiceName, output)
return "", err
}
}
return "", nil
}
func (c Configurd) ServiceDeployments(baseDir, namespace, deployment string) ([]ServiceDeployment, error) {
file, err := os.Open(path.Join(baseDir, defaultNamespaceDir, namespace, deployment+defaultConfigFileExt))
defer file.Close()
if err != nil {
return []ServiceDeployment{}, err
}
var wrapper struct {
ServiceDeployments []ServiceDeployment `yaml:"services"`
}
if err := yaml.NewDecoder(file).Decode(&wrapper); err != nil {
return []ServiceDeployment{}, fmt.Errorf("could not decode service: %w", err)
}
for i, sd := range wrapper.ServiceDeployments {
svc, err := c.Service(sd.ServiceName)
if err != nil {
log.Fatal(err)
}
wrapper.ServiceDeployments[i].chart = svc.Chart
wrapper.ServiceDeployments[i].namespace = namespace
}
return wrapper.ServiceDeployments, nil
}