Skip to content

Commit

Permalink
- Improved logging output
Browse files Browse the repository at this point in the history
- Added new zero downtime deployment recipe
  • Loading branch information
davesavic committed Jan 4, 2024
1 parent 62438a1 commit d7dc7eb
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 45 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ To get started with Ploy, follow these steps:
3. **Customize Configuration**: Edit the generated `configuration.json` to suit your deployment and task requirements.
4. **Run Ploy**: Execute your configurations using `ploy run [pipelines (run multiple separated by a space)]`.

### Recipes
- [Zero Downtime Deployments](https://github.com/davesavic/ploy/recipes/zero-downtime-deployment.json)

### Contributing
Contributions to Ploy are welcome!
If you have suggestions, bug reports, or want to contribute code, please visit create the relevant report.
10 changes: 7 additions & 3 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ var runCmd = &cobra.Command{
Short: "Run a ploy pipeline",
Long: `Run a ploy pipeline`,
Run: func(cmd *cobra.Command, args []string) {
cf, err := os.ReadFile("configuration.json")
configPath, _ := cmd.Flags().GetString("config")
cf, err := os.ReadFile(configPath)
if err != nil {
log.Fatal(err)
}
Expand All @@ -37,11 +38,12 @@ var runCmd = &cobra.Command{
for _, arg := range args {
var executor ploy.PipelineExecutor
local, _ := cmd.Flags().GetBool("local")
verbose, _ := cmd.Flags().GetBool("verbose")

if local {
executor = &ploy.LocalPipelineExecutor{Config: cfg}
executor = &ploy.LocalPipelineExecutor{Config: cfg, Verbose: verbose}
} else {
executor = &ploy.RemotePipelineExecutor{Config: cfg}
executor = &ploy.RemotePipelineExecutor{Config: cfg, Verbose: verbose}
}

out, err := executor.Execute(arg)
Expand All @@ -58,4 +60,6 @@ func init() {
rootCmd.AddCommand(runCmd)

runCmd.Flags().BoolP("local", "l", false, "Run the pipeline locally")
runCmd.Flags().String("config", "configuration.json", "Path to configuration file")
runCmd.Flags().BoolP("verbose", "v", false, "Verbose output")
}
82 changes: 45 additions & 37 deletions coverage.out
Original file line number Diff line number Diff line change
@@ -1,38 +1,46 @@
mode: set
github.com/davesavic/ploy/pkg/ploy/ploy.go:49.75,51.13 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:51.13,53.3 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:55.2,57.26 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:57.26,59.3 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:61.2,61.31 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:61.31,65.14 3 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:65.14,67.4 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:69.3,70.17 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:70.17,72.4 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:74.3,75.17 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:75.17,77.4 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:79.3,88.17 3 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:88.17,90.4 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:92.3,92.30 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:92.30,94.15 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:94.15,96.5 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:98.4,98.31 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:98.31,101.19 3 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:101.19,103.6 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:105.5,106.19 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:106.19,108.6 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:110.5,112.60 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:112.60,114.6 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:118.3,118.40 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:118.40,120.4 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:123.2,123.26 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:126.53,130.27 3 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:130.27,132.3 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:139.74,143.13 3 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:143.13,145.3 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:147.2,147.29 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:147.29,149.14 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:149.14,151.4 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:153.3,153.26 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:153.26,160.18 6 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:160.18,162.5 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:166.2,166.26 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:50.75,52.13 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:52.13,54.3 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:56.2,58.26 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:58.26,60.3 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:62.2,62.31 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:62.31,66.14 3 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:66.14,68.4 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:70.3,71.17 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:71.17,73.4 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:75.3,76.17 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:76.17,78.4 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:80.3,80.16 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:80.16,82.4 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:84.3,93.17 3 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:93.17,95.4 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:97.3,97.16 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:97.16,99.4 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:101.3,101.30 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:101.30,103.15 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:103.15,105.5 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:107.4,109.31 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:109.31,112.18 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:112.18,114.6 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:116.5,117.19 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:117.19,119.6 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:121.5,122.19 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:122.19,124.6 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:126.5,126.18 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:126.18,128.6 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:130.5,130.60 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:130.60,132.6 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:136.3,136.40 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:136.40,138.4 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:141.2,141.26 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:144.53,148.27 3 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:148.27,150.3 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:158.74,162.13 3 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:162.13,164.3 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:166.2,166.29 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:166.29,168.14 2 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:168.14,170.4 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:172.3,172.26 1 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:172.26,179.18 6 1
github.com/davesavic/ploy/pkg/ploy/ploy.go:179.18,181.5 1 0
github.com/davesavic/ploy/pkg/ploy/ploy.go:185.2,185.26 1 1
27 changes: 23 additions & 4 deletions pkg/ploy/ploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ type PipelineExecutor interface {
}

type RemotePipelineExecutor struct {
Config Config
Config Config
Verbose bool
}

func (r *RemotePipelineExecutor) Execute(pipeline string) (string, error) {
Expand All @@ -59,7 +60,7 @@ func (r *RemotePipelineExecutor) Execute(pipeline string) (string, error) {
}

for _, s := range pl.Servers {
out.Write([]byte(fmt.Sprintf("Running pipeline %s on server %s\n", pipeline, s)))
out.Write([]byte(fmt.Sprintf("Running pipeline [%s] on server [%s]\n", pipeline, s)))

server, exists := r.Config.Servers[s]
if !exists {
Expand All @@ -76,6 +77,10 @@ func (r *RemotePipelineExecutor) Execute(pipeline string) (string, error) {
return "", fmt.Errorf("error parsing private key (%s): %v", server.PrivateKey, err)
}

if r.Verbose {
out.Write([]byte(" Private key successfully loaded\n"))
}

sshCfg := ssh.ClientConfig{
User: server.User,
Auth: []ssh.AuthMethod{
Expand All @@ -89,14 +94,25 @@ func (r *RemotePipelineExecutor) Execute(pipeline string) (string, error) {
return "", fmt.Errorf("error dialing SSH server (%s): %v", s, err)
}

if r.Verbose {
out.Write([]byte(" SSH connection established\n"))
}

for _, t := range pl.Tasks {
commands, exists := r.Config.Tasks[t]
if !exists {
return "", fmt.Errorf("task %s is not defined", t)
}

out.Write([]byte(fmt.Sprintf(" Running task: %s\n", t)))

for _, c := range commands {
populatePlaceholders(&c, r.Config.Params)

if r.Verbose {
out.Write([]byte(fmt.Sprintf(" Executing: %s\n", c)))
}

session, err := client.NewSession()
if err != nil {
return "", fmt.Errorf("error creating SSH session: %v", err)
Expand All @@ -107,7 +123,9 @@ func (r *RemotePipelineExecutor) Execute(pipeline string) (string, error) {
return "", fmt.Errorf("error running command (%s): %v", c, err)
}

out.Write(op)
if r.Verbose {
out.Write([]byte(fmt.Sprintf(" Output: %s\n\n", op)))
}

if err := session.Close(); err != nil && err != io.EOF {
return "", fmt.Errorf("error closing SSH session: %v", err)
Expand All @@ -133,7 +151,8 @@ func populatePlaceholders(s *string, params Params) {
}

type LocalPipelineExecutor struct {
Config Config
Config Config
Verbose bool
}

func (l *LocalPipelineExecutor) Execute(pipeline string) (string, error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/ploy/ploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func TestRemotePipelineExecutor_Execute2(t *testing.T) {
{
name: "valid execution",
pipeline: "test",
expectedOutput: "Hello, World!",
expectedOutput: "Running task",
prepareFunc: func() (*SSHTestServer, ploy.Config) {
s := NewSSHTestServer("localhost:2222")
s.SetOutputString("Hello, World!")
Expand Down
58 changes: 58 additions & 0 deletions recipes/zero-downtime-deployment.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"params": {
"deployment-dir": "/srv/www/app/",
"serving-dir": "/srv/www/app/current",
"retention": "5",
"timestamp-file": "/tmp/deployment_timestamp"
},
"servers": {
"staging": {
"host": "111.111.111.111",
"port": 22,
"user": "ploy",
"private-key": "/home/user/.ssh/id_rsa"
}
},
"tasks": {
"generate-timestamp": [
"echo '{{timestamp}}' > {{timestamp-file}}"
],
"create-deployment-dir": [
"timestamp=$(cat {{timestamp-file}}) && mkdir -p {{deployment-dir}}$timestamp"
],
"deploy-app": [
"timestamp=$(cat {{timestamp-file}}) && touch {{deployment-dir}}$timestamp/deployed.txt"
],
"update-symlink": [
"timestamp=$(cat {{timestamp-file}}) && ln -sfn {{deployment-dir}}$timestamp {{serving-dir}}"
],
"cleanup-old-deployments": [
"ls -1 {{deployment-dir}} | grep -P '^\\d{14}$' | head -n -5 | xargs -I {} rm -rf {{deployment-dir}}{}"
],
"rollback-to-previous": [
"prev_deployment=$(ls -1 {{deployment-dir}} | grep -P '^\\d{14}$' | tail -n 2 | head -n 1) && ln -sfn {{deployment-dir}}$prev_deployment {{serving-dir}} && echo $prev_deployment > /tmp/current_deployment"
]
},
"pipelines": {
"deploy": {
"tasks": [
"generate-timestamp",
"create-deployment-dir",
"deploy-app",
"update-symlink",
"cleanup-old-deployments"
],
"servers": [
"staging"
]
},
"rollback": {
"tasks": [
"rollback-to-previous"
],
"servers": [
"staging"
]
}
}
}

0 comments on commit d7dc7eb

Please sign in to comment.