Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ stacks:

# The WEB UI address
address: 0.0.0.0:8080

# If you need the same values on every stack (domain names),
# you can define global values here instead of global.yaml file
# They can be overriden in the values file at stack level.
global_values:
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/m-adawi/swarm-cd
go 1.22.5

require (
github.com/Masterminds/sprig/v3 v3.2.1
github.com/docker/cli v27.0.3+incompatible
github.com/getsops/sops/v3 v3.9.0
github.com/gin-gonic/gin v1.10.0
Expand All @@ -27,6 +28,8 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.1 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/aws/aws-sdk-go-v2 v1.30.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect
github.com/aws/aws-sdk-go-v2/config v1.27.21 // indirect
Expand Down Expand Up @@ -80,6 +83,8 @@ require (
github.com/hashicorp/go-sockaddr v1.0.6 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/vault/api v1.14.0 // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.11 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
Expand All @@ -89,9 +94,11 @@ require (
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
Expand All @@ -100,6 +107,7 @@ require (
github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
Expand Down
21 changes: 21 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mx
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Masterminds/sprig/v3 v3.2.1 h1:n6EPaDyLSvCEa3frruQvAiHuNp2dhBlMSmkEr+HuzGc=
github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
Expand Down Expand Up @@ -297,6 +303,7 @@ github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
Expand Down Expand Up @@ -336,6 +343,11 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU=
github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
Expand Down Expand Up @@ -400,13 +412,17 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/miekg/pkcs11 v1.0.2 h1:CIBkOawOtzJNE0B+EpRiUBzuVW7JEQAwdwhSS6YhIeg=
github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/swarmkit/v2 v2.0.0-20240611172349-ea1a7cec35cb h1:1UTTg2EgO3nuyV03wREDzldqqePzQ4+0a5G1C1y1bIo=
Expand Down Expand Up @@ -496,6 +512,8 @@ github.com/samber/slog-gin v1.13.3 h1:BXVMDktx27zrr/PMYLvrEAOeIylBFtuemlQjgDUT3f
github.com/samber/slog-gin v1.13.3/go.mod h1:7+YTBV20co5pQ+802hgAncESKtcZMAOKFUBpuT8IhXo=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
Expand All @@ -509,6 +527,7 @@ github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIK
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
Expand Down Expand Up @@ -611,6 +630,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
Expand Down Expand Up @@ -755,6 +775,7 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
10 changes: 6 additions & 4 deletions swarmcd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import (
)

type StackStatus struct {
Error string
Revision string
RepoURL string
Error string
Revision string
RepoURL string
ComposePath string
TemplatePath string
}

var config *util.Config = &util.Configs
Expand Down Expand Up @@ -98,7 +100,7 @@ func initStacks() error {
return fmt.Errorf("error initializing %s stack, no such repo: %s", stack, stackConfig.Repo)
}
discoverSecrets := config.SopsSecretsDiscovery || stackConfig.SopsSecretsDiscovery
swarmStack := newSwarmStack(stack, stackRepo, stackConfig.Branch, stackConfig.ComposeFile, stackConfig.SopsFiles, stackConfig.ValuesFile, discoverSecrets)
swarmStack := newSwarmStack(stack, stackRepo, stackConfig.Branch, stackConfig.ComposeFile, stackConfig.SopsFiles, stackConfig.ValuesFile, discoverSecrets, config.GlobalValues, )
stacks = append(stacks, swarmStack)
stackStatus[stack] = &StackStatus{}
stackStatus[stack].RepoURL = stackRepo.url
Expand Down
40 changes: 25 additions & 15 deletions swarmcd/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"errors"
"fmt"
"log/slog"
"os"
"path"
"sync"

"github.com/go-git/go-git/v5"
Expand All @@ -12,25 +14,26 @@ import (
)

type stackRepo struct {
name string
lock *sync.Mutex
url string
gitRepoObject *git.Repository
auth *http.BasicAuth
path string
name string
lock *sync.Mutex
url string
gitRepoObject *git.Repository
auth *http.BasicAuth
path string
templateFolder string
}

func newStackRepo(name string, path string, url string, auth *http.BasicAuth) (*stackRepo, error) {
func newStackRepo(name string, repoPath string, url string, auth *http.BasicAuth) (*stackRepo, error) {
var repo *git.Repository
cloneOptions := &git.CloneOptions{
URL: url,
Auth: auth,
}
repo, err := git.PlainClone(path, false, cloneOptions)
repo, err := git.PlainClone(repoPath, false, cloneOptions)

if err != nil {
if errors.Is(err, git.ErrRepositoryAlreadyExists) {
repo, err = git.PlainOpen(path)
repo, err = git.PlainOpen(repoPath)
if err != nil {
return nil, fmt.Errorf("could not open existing repo %s: %w", name, err)
}
Expand All @@ -44,13 +47,20 @@ func newStackRepo(name string, path string, url string, auth *http.BasicAuth) (*
return nil, fmt.Errorf("could not clone repo %s: %w", name, err)
}
}

templateFolder := path.Join(repoPath, "template")
_, err = os.Stat(templateFolder)
if err != nil {
templateFolder = ""
}
return &stackRepo{
name: name,
path: path,
url: url,
auth: auth,
lock: &sync.Mutex{},
gitRepoObject: repo,
name: name,
path: repoPath,
url: url,
auth: auth,
lock: &sync.Mutex{},
gitRepoObject: repo,
templateFolder: templateFolder,
}, nil
}

Expand Down
81 changes: 67 additions & 14 deletions swarmcd/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import (
"crypto/md5"
"fmt"
"log/slog"
"maps"
"os"
"path"
"text/template"

"github.com/docker/cli/cli/command/stack"
"github.com/goccy/go-yaml"
"github.com/m-adawi/swarm-cd/util"
"github.com/Masterminds/sprig/v3"
)

type swarmStack struct {
Expand All @@ -22,9 +24,11 @@ type swarmStack struct {
sopsFiles []string
valuesFile string
discoverSecrets bool
globalValuesMap map[string]any
templateFolder string
}

func newSwarmStack(name string, repo *stackRepo, branch string, composePath string, sopsFiles []string, valuesFile string, discoverSecrets bool) *swarmStack {
func newSwarmStack(name string, repo *stackRepo, branch string, composePath string, sopsFiles []string, valuesFile string, discoverSecrets bool, globalValuesMap map[string]any) *swarmStack {
return &swarmStack{
name: name,
repo: repo,
Expand All @@ -33,6 +37,7 @@ func newSwarmStack(name string, repo *stackRepo, branch string, composePath stri
sopsFiles: sopsFiles,
valuesFile: valuesFile,
discoverSecrets: discoverSecrets,
globalValuesMap: globalValuesMap,
}
}

Expand All @@ -41,6 +46,20 @@ func (swarmStack *swarmStack) updateStack() (revision string, err error) {
slog.String("stack", swarmStack.name),
slog.String("branch", swarmStack.branch),
)

log.Debug("resetting cache dir...")
stackStatus[swarmStack.name].TemplatePath = ""
stackStatus[swarmStack.name].ComposePath = ""
cacheDir := path.Join("cache/stacks", swarmStack.name)
err = os.RemoveAll(cacheDir)
if err != nil {
return "", fmt.Errorf("could remove cache dir for stack %s: %s", swarmStack.name, err)
}

err = os.MkdirAll(cacheDir, 0750)
if err != nil {
return "", fmt.Errorf("could create cache dir for stack %s: %s", swarmStack.name, err)
}

log.Debug("pulling changes...")
revision, err = swarmStack.repo.pullChanges(swarmStack.branch)
Expand All @@ -51,18 +70,33 @@ func (swarmStack *swarmStack) updateStack() (revision string, err error) {

log.Debug("reading stack file...")
stackBytes, err := swarmStack.readStack()
originalStackBytes := bytes.Clone(stackBytes)
if err != nil {
return
}

mergedValuesMap := make(map[string]any)
maps.Copy(mergedValuesMap, swarmStack.globalValuesMap)

if swarmStack.valuesFile != "" {
log.Debug("rendering template...")
stackBytes, err = swarmStack.renderComposeTemplate(stackBytes)
valuesFile := path.Join(swarmStack.repo.path, swarmStack.valuesFile)
var valuesMap map[string]any
valuesMap, err = util.ParseValuesFile(valuesFile, swarmStack.name + " stack")
if err != nil {
return
}
maps.Copy(mergedValuesMap, valuesMap)
}
if err != nil {
return

if len(mergedValuesMap) > 0 || swarmStack.repo.templateFolder != "" {
log.Debug("rendering template...")
stackBytes, err = swarmStack.renderComposeTemplate(stackBytes, mergedValuesMap)
if err != nil {
return
}
}


log.Debug("parsing stack content...")
stackContents, err := swarmStack.parseStackString([]byte(stackBytes))
if err != nil {
Expand All @@ -87,6 +121,19 @@ func (swarmStack *swarmStack) updateStack() (revision string, err error) {
return
}

log.Debug("Writing cache files...")
if bytes.Compare(originalStackBytes, stackBytes) != 0 {
templateCachePath := path.Join(cacheDir, "template.yaml")
err = os.WriteFile(templateCachePath, originalStackBytes, 0640)
if err != nil {
return "", fmt.Errorf("could not save a copy of stack %s original template to %s: %s", swarmStack.name, templateCachePath, err)
}
stackStatus[swarmStack.name].TemplatePath = templateCachePath
}
composeCache := path.Join(cacheDir, "compose.yaml")
os.WriteFile(composeCache, stackBytes, 0640)
stackStatus[swarmStack.name].ComposePath = composeCache

log.Debug("deploying stack...")
err = swarmStack.deployStack()
return
Expand All @@ -101,18 +148,24 @@ func (swarmStack *swarmStack) readStack() ([]byte, error) {
return composeFileBytes, nil
}

func (swarmStack *swarmStack) renderComposeTemplate(templateContents []byte) ([]byte, error) {
valuesFile := path.Join(swarmStack.repo.path, swarmStack.valuesFile)
valuesBytes, err := os.ReadFile(valuesFile)
if err != nil {
return nil, fmt.Errorf("could not read %s stack values file: %w", swarmStack.name, err)
}
var valuesMap map[string]any
yaml.Unmarshal(valuesBytes, &valuesMap)
templ, err := template.New(swarmStack.name).Parse(string(templateContents[:]))
func (swarmStack *swarmStack) renderComposeTemplate(templateContents []byte, valuesMap map[string]any) ([]byte, error) {
log := logger.With(
slog.String("stack", swarmStack.name),
slog.String("branch", swarmStack.branch),
)
templ, err := template.New(swarmStack.name).Funcs(sprig.FuncMap()).Parse(string(templateContents[:]))
if err != nil {
return nil, fmt.Errorf("could not parse %s stack compose file as a Go template: %w", swarmStack.name, err)
}

if swarmStack.repo.templateFolder != "" {
log.Debug("Loading template folder...")
_, err = templ.ParseGlob(path.Join(swarmStack.repo.templateFolder, "*.tmpl"))
if err != nil {
return nil, err
}
}

var stackContents bytes.Buffer
err = templ.Execute(&stackContents, map[string]map[string]any{"Values": valuesMap})
if err != nil {
Expand Down
Loading