Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit 64390aa

Browse files
committed
feat: project deployment versions
1 parent 3e602c1 commit 64390aa

File tree

19 files changed

+362
-150
lines changed

19 files changed

+362
-150
lines changed

commands/project/deploy.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ var DeployApplication = func() *cobra.Command {
5454
} else {
5555
// Confirm resource creation
5656
fmt.Println("\nStackHead will try to create or update the following resources:")
57-
for _, resourceGroup := range system.Context.Resources {
57+
for _, resourceGroup := range system.Context.CurrentDeployment.ResourceGroups {
5858
for _, resource := range resourceGroup.Resources {
5959
fmt.Println(fmt.Sprintf("- %s", resource.ToString(false)))
6060
}

modules/container/docker/definitions/volume.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,27 @@ package container_docker_definitions
33
import (
44
"github.com/getstackhead/stackhead/project"
55
"github.com/getstackhead/stackhead/system"
6+
"path"
67
)
78

89
type DockerPaths struct {
9-
BaseDir string
10+
DataDir string
11+
DeploymentDir string
1012
}
1113

1214
func GetDockerPaths() DockerPaths {
1315
return DockerPaths{
14-
BaseDir: system.Context.Project.GetRuntimeDataDirectoryPath() + "/container",
16+
DataDir: path.Join(system.Context.Project.GetRuntimeDataDirectoryPath(), "container"),
17+
DeploymentDir: path.Join(system.Context.CurrentDeployment.GetPath(), "container"),
1518
}
1619
}
1720

1821
func (p DockerPaths) GetHooksDir() string {
19-
return p.BaseDir + "/hooks"
22+
return path.Join(p.DeploymentDir, "hooks")
2023
}
2124

2225
func (p DockerPaths) getDataDir() string {
23-
return p.BaseDir + "/data"
26+
return path.Join(p.DataDir, "data")
2427
}
2528

2629
func (p DockerPaths) GetServiceDataDir(service project.ContainerService, volume project.ContainerServiceVolume) string {

modules/container/docker/deploy.go

+58-31
Original file line numberDiff line numberDiff line change
@@ -138,25 +138,36 @@ func (m Module) Deploy(modulesSettings interface{}) error {
138138
return err
139139
}
140140

141-
composeFileRemotePath := system.Context.Project.GetDirectoryPath() + "/docker-compose.yaml"
142-
143-
hasRemoteFile, err := xfs.HasFile("ssh://" + composeFileRemotePath)
144-
if err != nil && err.Error() == "file does not exist" {
145-
hasRemoteFile = false
146-
} else if err != nil {
147-
return fmt.Errorf("Unable to check state of remote docker-compose.yaml from previous deployment: " + err.Error())
141+
dockerComposeResource := system.Resource{
142+
Type: system.TypeFile,
143+
Operation: system.OperationCreate,
144+
Name: "docker-compose.yaml",
148145
}
149146

147+
oldComposeFilePath := ""
150148
var remoteComposeObjMap map[string]interface{}
151-
if hasRemoteFile {
152-
remoteComposeObj := docker_compose.DockerCompose{}
153-
remoteComposeContent, err := xfs.ReadFile("ssh://" + composeFileRemotePath)
154-
if err := yaml.Unmarshal([]byte(remoteComposeContent), &remoteComposeObj); err != nil {
155-
return fmt.Errorf("unable to read remote docker-compose.yaml file from previous deployment: " + err.Error())
156-
}
157-
remoteComposeObjMap, err = remoteComposeObj.Map()
149+
if system.Context.LatestDeployment != nil {
150+
dockerComposeFilePathOld, err := system.Context.LatestDeployment.GetResourcePath(dockerComposeResource)
158151
if err != nil {
159-
return fmt.Errorf("unable to process remote docker-compose.yaml file from previous deployment: " + err.Error())
152+
return err
153+
}
154+
oldComposeFilePath = dockerComposeFilePathOld
155+
hasRemoteFile, err := xfs.HasFile("ssh://" + oldComposeFilePath)
156+
if err != nil && hasRemoteFile {
157+
remoteComposeContent, err := xfs.ReadFile("ssh://" + oldComposeFilePath)
158+
if err != nil {
159+
return fmt.Errorf("unable to read remote docker-compose.yaml file from previous deployment: " + err.Error())
160+
}
161+
remoteComposeObj := docker_compose.DockerCompose{}
162+
if err := yaml.Unmarshal([]byte(remoteComposeContent), &remoteComposeObj); err != nil {
163+
return fmt.Errorf("unable to read remote docker-compose.yaml file from previous deployment: " + err.Error())
164+
}
165+
remoteComposeObjMap, err = remoteComposeObj.Map()
166+
if err != nil {
167+
return fmt.Errorf("unable to process remote docker-compose.yaml file from previous deployment: " + err.Error())
168+
}
169+
} else if err != nil && err.Error() != "file does not exist" {
170+
return fmt.Errorf("Unable to check state of remote docker-compose.yaml from previous deployment: " + err.Error())
160171
}
161172
}
162173

@@ -177,17 +188,13 @@ func (m Module) Deploy(modulesSettings interface{}) error {
177188
if err != nil {
178189
return err
179190
}
191+
dockerComposeResource.Content = composeFileContent
180192

181-
system.Context.Resources = append(system.Context.Resources, system.ResourceGroup{
182-
Name: "container-docker-" + system.Context.Project.Name + "-composefile",
183-
Resources: []system.Resource{
184-
{
185-
Type: system.TypeFile,
186-
Operation: system.OperationCreate,
187-
Name: composeFileRemotePath,
188-
Content: composeFileContent,
189-
},
190-
},
193+
dockerComposeFilePathNew, _ := system.Context.CurrentDeployment.GetResourcePath(dockerComposeResource)
194+
195+
system.Context.CurrentDeployment.ResourceGroups = append(system.Context.CurrentDeployment.ResourceGroups, system.ResourceGroup{
196+
Name: "container-docker-" + system.Context.Project.Name + "-composefile",
197+
Resources: []system.Resource{dockerComposeResource},
191198
})
192199

193200
var containerResources []system.Resource
@@ -202,14 +209,24 @@ func (m Module) Deploy(modulesSettings interface{}) error {
202209
})
203210
}
204211

205-
system.Context.Resources = append(system.Context.Resources, system.ResourceGroup{
212+
system.Context.CurrentDeployment.ResourceGroups = append(system.Context.CurrentDeployment.ResourceGroups, system.ResourceGroup{
206213
Name: "container-docker-" + system.Context.Project.Name + "-containers",
207214
Resources: containerResources,
208215
ApplyResourceFunc: func() error {
216+
if oldComposeFilePath != "" {
217+
// Stop old Docker Compose containers
218+
// todo: allow using either docker-compose or "docker compose" whichever is available (prefer "docker compose")
219+
if _, stderr, err := system.RemoteRun("docker compose", system.RemoteRunOpts{Args: []string{"down"}, WorkingDir: path.Dir(oldComposeFilePath)}); err != nil {
220+
if stderr.Len() > 0 {
221+
return fmt.Errorf("Unable to stop old Docker containers: " + stderr.String())
222+
}
223+
return fmt.Errorf("Unable to stop old Docker containers: " + err.Error())
224+
}
225+
}
226+
209227
// Start Docker Compose
210228
// todo: allow using either docker-compose or "docker compose" whichever is available (prefer "docker compose")
211-
_, stderr, err := system.RemoteRun("docker compose", system.RemoteRunOpts{Args: []string{"up", "-d"}, WorkingDir: system.Context.Project.GetDirectoryPath()})
212-
if err != nil {
229+
if _, stderr, err := system.RemoteRun("docker compose", system.RemoteRunOpts{Args: []string{"up", "-d"}, WorkingDir: path.Dir(dockerComposeFilePathNew)}); err != nil {
213230
if stderr.Len() > 0 {
214231
return fmt.Errorf("Unable to start Docker containers: " + stderr.String())
215232
}
@@ -223,14 +240,24 @@ func (m Module) Deploy(modulesSettings interface{}) error {
223240
return nil
224241
},
225242
RollbackResourceFunc: func() error {
243+
// Start old containers again
244+
if oldComposeFilePath != "" {
245+
// todo: allow using either docker-compose or "docker compose" whichever is available (prefer "docker compose")
246+
if _, stderr, err := system.RemoteRun("docker compose", system.RemoteRunOpts{Args: []string{"up", "-d"}, WorkingDir: path.Dir(oldComposeFilePath)}); err != nil {
247+
if stderr.Len() > 0 {
248+
return fmt.Errorf("Unable to stop Docker containers: " + stderr.String())
249+
}
250+
return fmt.Errorf("Unable to start old Docker containers: " + err.Error())
251+
}
252+
}
253+
226254
// Stop Docker Compose
227255
// todo: allow using either docker-compose or "docker compose" whichever is available (prefer "docker compose")
228-
_, stderr, err := system.RemoteRun("docker compose", system.RemoteRunOpts{Args: []string{"down"}, WorkingDir: system.Context.Project.GetDirectoryPath()})
229-
if err != nil {
256+
if _, stderr, err := system.RemoteRun("docker compose", system.RemoteRunOpts{Args: []string{"down"}, WorkingDir: path.Dir(dockerComposeFilePathNew)}); err != nil {
230257
if stderr.Len() > 0 {
231258
return fmt.Errorf("Unable to stop Docker containers: " + stderr.String())
232259
}
233-
return fmt.Errorf("Unable to stop Docker containers: " + err.Error())
260+
return fmt.Errorf("Unable to stop new Docker containers: " + err.Error())
234261
}
235262
return nil
236263
},

modules/container/docker/destroy.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func (m Module) Destroy(modulesSettings interface{}) error {
1515

1616
// Stop and remove containers
1717
// todo: allow using either docker-compose or "docker compose" whichever is available (prefer "docker compose")
18-
_, stderr, err := system.RemoteRun("docker compose", system.RemoteRunOpts{Args: []string{"down"}, WorkingDir: system.Context.Project.GetDirectoryPath()})
18+
_, stderr, err := system.RemoteRun("docker compose", system.RemoteRunOpts{Args: []string{"down"}, WorkingDir: system.Context.CurrentDeployment.GetPath()})
1919
if err != nil {
2020
if stderr.Len() > 0 {
2121
return fmt.Errorf("Unable to stop Docker containers: " + stderr.String())

modules/container/docker/docker-compose/yaml.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ func BuildDockerCompose(project *project.Project) (DockerCompose, error) {
1717
dockerPaths := container_docker_definitions.GetDockerPaths()
1818
compose := DockerCompose{
1919
Version: "2.4",
20-
Networks: map[string]Network{"stackhead-network-" + project.Name: {}},
20+
Networks: map[string]Network{docker_system.NetworkName(project.Name, system.Context.CurrentDeployment): {}},
2121
Services: map[string]Services{},
2222
Volumes: map[string]Volume{},
2323
}
@@ -36,7 +36,6 @@ func BuildDockerCompose(project *project.Project) (DockerCompose, error) {
3636
continue
3737
}
3838
vol := Volume{}
39-
serviceName := service.Name
4039
vol.DriverOpts.Type = "none"
4140
vol.DriverOpts.O = "bind"
4241
if volume.Type == "local" {
@@ -46,7 +45,7 @@ func BuildDockerCompose(project *project.Project) (DockerCompose, error) {
4645
} else if volume.Type == "custom" {
4746
vol.DriverOpts.Device = volume.Src
4847
}
49-
compose.Volumes[GetVolumeSrcKey(project.Name, serviceName, volume)] = vol
48+
compose.Volumes[GetVolumeSrcKey(project.Name, service.Name, volume)] = vol
5049
}
5150
}
5251

@@ -89,12 +88,12 @@ func addService(compose *DockerCompose, project *project.Project, service projec
8988
}
9089

9190
compose.Services[service.Name] = Services{
92-
ContainerName: docker_system.ContainerName(project.Name, service.Name),
91+
ContainerName: docker_system.ContainerName(project.Name, service.Name, system.Context.CurrentDeployment),
9392
Image: service.Image,
9493
Restart: "unless-stopped",
9594
Labels: map[string]string{"stackhead.project": project.Name},
9695
User: service.User,
97-
Networks: map[string]ServiceNetwork{"stackhead-network-" + project.Name: {Aliases: []string{service.Name}}},
96+
Networks: map[string]ServiceNetwork{docker_system.NetworkName(project.Name, system.Context.CurrentDeployment): {Aliases: []string{service.Name}}},
9897
Volumes: volumes,
9998
Ports: ports,
10099
Environment: service.Environment,

modules/container/docker/system/hooks.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ func ExecuteHook(hookName string) error {
4545

4646
// copy file onto container and run it.....
4747
containerLocation := path.Join("/", file.File)
48-
containerName := ContainerName(system.Context.Project.Name, file.Service)
48+
containerName := ContainerName(system.Context.Project.Name, file.Service, system.Context.CurrentDeployment)
4949
_, err := system.SimpleRemoteRun("docker", system.RemoteRunOpts{
5050
Args: []string{
5151
"cp",
5252
filePath,
5353
containerName + ":" + containerLocation,
5454
},
55-
WorkingDir: system.Context.Project.GetDirectoryPath(),
55+
WorkingDir: system.Context.CurrentDeployment.GetPath(),
5656
})
5757
if err != nil {
5858
return fmt.Errorf("Unable to copy file %s to container %s: \"%s\"", file.File, containerName, err.Error())
@@ -64,7 +64,7 @@ func ExecuteHook(hookName string) error {
6464
containerName,
6565
"chmod +x " + containerLocation,
6666
},
67-
WorkingDir: system.Context.Project.GetDirectoryPath(),
67+
WorkingDir: system.Context.CurrentDeployment.GetPath(),
6868
})
6969
if err != nil {
7070
return fmt.Errorf("Unable to copy file %s to container %s: \"%s\"", file.File, containerName, err.Error())
@@ -76,7 +76,7 @@ func ExecuteHook(hookName string) error {
7676
containerName,
7777
containerLocation,
7878
},
79-
WorkingDir: system.Context.Project.GetDirectoryPath(),
79+
WorkingDir: system.Context.CurrentDeployment.GetPath(),
8080
})
8181
if err != nil {
8282
return fmt.Errorf("Unable to run %s on container %s: \"%s\"", file, containerName, err.Error())
+10-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
package docker_system
22

3-
import "fmt"
3+
import (
4+
"fmt"
5+
"github.com/getstackhead/stackhead/system"
6+
)
47

5-
func ContainerName(projectName string, serviceName string) string {
6-
return fmt.Sprintf("stackhead-%s-%s", projectName, serviceName)
8+
func ContainerName(projectName string, serviceName string, deployment system.Deployment) string {
9+
return fmt.Sprintf("stackhead-%s-%s-v%d", projectName, serviceName, deployment.Version)
10+
}
11+
12+
func NetworkName(projectName string, deployment system.Deployment) string {
13+
return fmt.Sprintf("stackhead-network-%s-v%d", projectName, deployment.Version)
714
}

modules/container/docker/system/ports.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func GetPortMap(project *project.Project) (map[string]int, error) {
1616

1717
// find ports for running containers
1818
for _, service := range project.Container.Services {
19-
res, _, err := system.RemoteRun("docker", system.RemoteRunOpts{Args: []string{"port", "stackhead-" + project.Name + "-" + service.Name}})
19+
res, _, err := system.RemoteRun("docker", system.RemoteRunOpts{Args: []string{"port", ContainerName(project.Name, service.Name, system.Context.CurrentDeployment)}})
2020
if err == nil { // ignore error (container not running)
2121
// e.g. 80/tcp -> 0.0.0.0:49155
2222
re := regexp.MustCompile(`(?P<Internal>\d+)\/tcp -> 0\.0\.0\.0:(?P<External>\d+)`)

modules/container/docker/templates/project.tf.tmpl

-17
This file was deleted.

modules/proxy/caddy/deploy.go

+15-12
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,23 @@ func (Module) Deploy(modulesSettings interface{}) error {
1717
return err
1818
}
1919

20-
projectCaddyLocation := system.Context.Project.GetDirectoryPath() + "/Caddyfile"
20+
caddyFileResource := system.Resource{
21+
Type: system.TypeFile,
22+
Operation: system.OperationCreate,
23+
Name: "Caddyfile",
24+
Content: caddyDirectives,
25+
}
2126

22-
system.Context.Resources = append(system.Context.Resources, system.ResourceGroup{
23-
Name: "proxy-caddy-" + system.Context.Project.Name + "-caddyfile",
24-
Resources: []system.Resource{
25-
{
26-
Type: system.TypeFile,
27-
Operation: system.OperationCreate,
28-
Name: projectCaddyLocation,
29-
Content: caddyDirectives,
30-
},
31-
},
27+
caddyFilePath, err := system.Context.CurrentDeployment.GetResourcePath(caddyFileResource)
28+
if err != nil {
29+
return err
30+
}
31+
32+
system.Context.CurrentDeployment.ResourceGroups = append(system.Context.CurrentDeployment.ResourceGroups, system.ResourceGroup{
33+
Name: "proxy-caddy-" + system.Context.Project.Name + "-caddyfile",
34+
Resources: []system.Resource{caddyFileResource},
3235
ApplyResourceFunc: func() error {
33-
if _, err := system.SimpleRemoteRun("ln", system.RemoteRunOpts{Args: []string{"-sf " + projectCaddyLocation + " /etc/caddy/conf.d/stackhead_" + system.Context.Project.Name + ".conf"}}); err != nil {
36+
if _, err := system.SimpleRemoteRun("ln", system.RemoteRunOpts{Args: []string{"-sf " + caddyFilePath + " /etc/caddy/conf.d/stackhead_" + system.Context.Project.Name + ".conf"}}); err != nil {
3437
return fmt.Errorf("Unable to symlink project Caddyfile: " + err.Error())
3538
}
3639
if _, err := system.SimpleRemoteRun("systemctl", system.RemoteRunOpts{Args: []string{"reload", "caddy"}, Sudo: true}); err != nil {

modules/proxy/nginx/certificates.go

-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ func GetSnakeoilPaths() (string, string) {
1414
return path.Join(CertificatesDirectory, "fullchain_snakeoil.pem"), path.Join(CertificatesDirectory, "privkey_snakeoil.pem")
1515
}
1616

17-
func GetCertificateDirectoryPath(p *project.Project) string {
18-
return path.Join(config.ProjectsRootDirectory, p.Name, "certificates")
19-
}
20-
2117
func GetCertificatesDirectory(p *project.Project) string {
2218
return path.Join(CertificatesDirectory, p.Name)
2319
}

0 commit comments

Comments
 (0)