kitsune-kit 0.2.1 โ†’ 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd66d70ec00aa522857e3ac981a13ada8e49aa5723e1a1fc577bc05b7642e250
4
- data.tar.gz: 81121119b1abe6a5b70d9fb59efc96994af2ac144b899e96bb5a0098743ee995
3
+ metadata.gz: 508f86259061cf1c767fc1a1678aeb8195aaf174214c2c7f9be5557aa1b73c2a
4
+ data.tar.gz: 38f6179c02ad9a59608bb3e3d3f62bd7b23648bb0bb24a6cdbd9fba179af3255
5
5
  SHA512:
6
- metadata.gz: 2a49fd2827e0edc77b9a40a8a7b42fef05cb9ba4c6a78655de2419022ec9ad98b703073620643dca76024184557d146e5c67a8fc6536c7596a52a2b13379d5a5
7
- data.tar.gz: 8f2d905fd886ba016229e13762e63b9c1997d9289619bf9d3a3793bd222e8a330231884c64d9dba9571a1ebe32fe7f421c84da29e3c064ebce2eb24faa639931
6
+ metadata.gz: 65b84489d96cc8228afe78113dcd08065d3297957b77fcece8dfb9fe1d5722695086f18cc6387c400a9888342ac82ce56feaa7d2f9d67c780bf6abedb4c7da3e
7
+ data.tar.gz: 59a28feaca900d703eb9ebe9943993cb1709b66784d7160425dc50f682bf7e93296408f8cdaedac04f3b2583a7757e74e69f7538515cc83abf3bf0f7088a1411
data/README.md CHANGED
@@ -19,7 +19,8 @@
19
19
  - ๐Ÿ’พ Configures swap space for better performance
20
20
  - ๐Ÿ“Š Installs [DigitalOcean monitoring agent](https://docs.digitalocean.com/products/monitoring/how-to/install-agent/)
21
21
  - ๐Ÿณ Installs and configures Docker Engine and private networking
22
- - ๐Ÿ˜ Deploys PostgreSQL via Docker Compose with healthcheck and `.env`
22
+ - ๐Ÿ˜ Deploys PostgreSQL via Docker Compose with healthcheck
23
+ - ๐Ÿ—„๏ธ Deploys Redis via Docker Compose with healthcheck
23
24
  - ๐Ÿ”„ All steps can be rolled back (`--rollback`)
24
25
  - โšก Fast, reproducible and without relying on YAML or complex external tools
25
26
 
@@ -17,6 +17,10 @@ SWAP_SIZE_GB=2
17
17
  DISABLE_SWAP=false
18
18
 
19
19
  # PostgreSQL Docker
20
- POSTGRES_DB=
21
- POSTGRES_USER=
22
- POSTGRES_PASSWORD=
20
+ POSTGRES_DB=myapp_db
21
+ POSTGRES_USER=postgres
22
+ POSTGRES_PASSWORD=secret
23
+
24
+ # Redis Docker
25
+ REDIS_PORT=6379
26
+ REDIS_PASSWORD=secret
@@ -0,0 +1,23 @@
1
+ services:
2
+ redis:
3
+ image: redis:7.2
4
+ restart: always
5
+ ports:
6
+ - "${REDIS_PORT:-6379}:6379"
7
+ command: redis-server --requirepass ${REDIS_PASSWORD}
8
+ networks:
9
+ - private
10
+ volumes:
11
+ - redisdata:/data
12
+ healthcheck:
13
+ test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
14
+ interval: 30s
15
+ timeout: 10s
16
+ retries: 5
17
+
18
+ volumes:
19
+ redisdata:
20
+
21
+ networks:
22
+ private:
23
+ driver: bridge
@@ -15,18 +15,29 @@ require_relative "commands/install_docker_engine"
15
15
  require_relative "commands/postinstall_docker"
16
16
  require_relative "commands/bootstrap_docker"
17
17
  require_relative "commands/setup_postgres_docker"
18
+ require_relative "commands/setup_redis_docker"
18
19
 
19
20
  module Kitsune
20
21
  module Kit
21
22
  class CLI < Thor
22
23
  def self.dispatch(m, args, options, config)
23
- unless ["init", "switch_env", "help", nil].include?(args.first)
24
+ if args.include?("-v") || args.include?("--version")
25
+ puts "Kitsune Kit v#{Kitsune::Kit::VERSION}"
26
+ exit(0)
27
+ end
28
+
29
+ unless ["version", "init", "switch_env", "help", nil].include?(args.first)
24
30
  Kitsune::Kit::EnvLoader.load!
25
31
  end
26
32
 
27
33
  super
28
34
  end
29
35
 
36
+ desc "version", "Show Kitsune Kit version"
37
+ def version
38
+ say "Kitsune Kit v#{Kitsune::Kit::VERSION}", :green
39
+ end
40
+
30
41
  desc "init", "Initialize Kitsune Kit project structure"
31
42
  subcommand "init", Kitsune::Kit::Commands::Init
32
43
 
@@ -68,6 +79,9 @@ module Kitsune
68
79
 
69
80
  desc "setup_postgres_docker SUBCOMMAND", "Setup PostgreSQL via Docker Compose on remote server"
70
81
  subcommand "setup_postgres_docker", Kitsune::Kit::Commands::SetupPostgresDocker
82
+
83
+ desc "setup_redis_docker SUBCOMMAND", "Setup Redis via Docker Compose on remote server"
84
+ subcommand "setup_redis_docker", Kitsune::Kit::Commands::SetupRedisDocker
71
85
  end
72
86
  end
73
87
  end
@@ -124,8 +124,8 @@ module Kitsune
124
124
  end
125
125
 
126
126
  def copy_docker_templates
127
- dest_path = ".kitsune/docker/postgres.yml"
128
- copy_with_prompt(blueprint_path("docker/postgres.yml"), dest_path)
127
+ copy_with_prompt(blueprint_path("docker/postgres.yml"), ".kitsune/docker/postgres.yml")
128
+ copy_with_prompt(blueprint_path("docker/redis.yml"), ".kitsune/docker/redis.yml")
129
129
  end
130
130
 
131
131
  def copy_with_prompt(source, destination)
@@ -26,7 +26,7 @@ module Kitsune
26
26
  defaults: Kitsune::Kit::Defaults.ssh
27
27
  )
28
28
 
29
- with_ssh(filled_options) do |ssh|
29
+ with_ssh_connection(filled_options) do |ssh|
30
30
  install_agent(ssh)
31
31
  end
32
32
  end
@@ -39,13 +39,13 @@ module Kitsune
39
39
  defaults: Kitsune::Kit::Defaults.ssh
40
40
  )
41
41
 
42
- with_ssh(filled_options) do |ssh|
42
+ with_ssh_connection(filled_options) do |ssh|
43
43
  uninstall_agent(ssh)
44
44
  end
45
45
  end
46
46
 
47
47
  no_commands do
48
- def with_ssh(filled_options)
48
+ def with_ssh_connection(filled_options)
49
49
  Net::SSH.start(
50
50
  filled_options[:server_ip],
51
51
  "deploy",
@@ -36,11 +36,7 @@ module Kitsune
36
36
  )
37
37
 
38
38
  with_ssh_connection(filled_options) do |ssh|
39
- perform_setup(ssh, postgres_defaults)
40
-
41
- database_url = build_database_url(filled_options, postgres_defaults)
42
- say "๐Ÿ”— Your DATABASE_URL is:\t", :cyan
43
- say database_url, :green
39
+ perform_setup(ssh, postgres_defaults, filled_options)
44
40
  end
45
41
  end
46
42
 
@@ -71,26 +67,21 @@ module Kitsune
71
67
  end
72
68
  end
73
69
 
74
- def perform_setup(ssh, postgres_defaults)
75
- docker_compose_local = ".kitsune/docker/postgres.yml"
76
- unless File.exist?(docker_compose_local)
77
- say "โŒ Docker compose file not found at #{docker_compose_local}.", :red
78
- exit(1)
79
- end
70
+ def perform_setup(ssh, postgres_defaults, filled_options)
71
+ local_compose = ".kitsune/docker/postgres.yml"
72
+ remote_dir = "$HOME/docker/postgres"
73
+ compose_remote = "#{remote_dir}/docker-compose.yml"
74
+ env_remote = "#{remote_dir}/.env"
75
+ marker = "/usr/local/backups/setup_postgres_docker.after"
80
76
 
81
- docker_dir_remote = "$HOME/docker/postgres"
82
- docker_compose_remote = "#{docker_dir_remote}/docker-compose.yml"
83
- docker_env_remote = "#{docker_dir_remote}/.env"
84
- backup_marker = "/usr/local/backups/setup_postgres_docker.after"
77
+ abort "โŒ Missing #{local_compose}" unless File.exist?(local_compose)
85
78
 
86
79
  # 1. Create base directory securely
87
- ssh.exec!("mkdir -p #{docker_dir_remote}")
88
- ssh.exec!("chmod 700 #{docker_dir_remote}")
80
+ ssh.exec!("mkdir -p #{remote_dir} && chmod 700 #{remote_dir}")
89
81
 
90
82
  # 2. Upload docker-compose.yml
91
- say "๐Ÿ“ฆ Uploading docker-compose.yml to remote server...", :cyan
92
- content_compose = File.read(docker_compose_local)
93
- upload_file(ssh, content_compose, docker_compose_remote)
83
+ say "๐Ÿ“ฆ Uploading docker-compose.yml to #{remote_dir}", :cyan
84
+ upload_file(ssh, File.read(local_compose), compose_remote)
94
85
 
95
86
  # 3. Create .env file for docker-compose based on postgres_defaults
96
87
  say "๐Ÿ“ฆ Creating .env file for Docker Compose...", :cyan
@@ -101,17 +92,17 @@ module Kitsune
101
92
  POSTGRES_PORT=#{postgres_defaults[:postgres_port]}
102
93
  POSTGRES_IMAGE=#{postgres_defaults[:postgres_image]}
103
94
  ENVFILE
104
- upload_file(ssh, env_content, docker_env_remote)
95
+ upload_file(ssh, env_content, env_remote)
105
96
 
106
97
  # 4. Secure file permissions
107
- ssh.exec!("chmod 600 #{docker_compose_remote} #{docker_env_remote}")
98
+ ssh.exec!("chmod 600 #{compose_remote} #{env_remote}")
108
99
 
109
100
  # 5. Create backup marker
110
- ssh.exec!("sudo mkdir -p /usr/local/backups && sudo touch #{backup_marker}")
101
+ ssh.exec!("sudo mkdir -p /usr/local/backups && sudo touch #{marker}")
111
102
 
112
103
  # 6. Validate docker-compose.yml
113
104
  say "๐Ÿ” Validating docker-compose.yml...", :cyan
114
- validation_output = ssh.exec!("cd #{docker_dir_remote} && docker compose config")
105
+ validation_output = ssh.exec!("cd #{remote_dir} && docker compose config")
115
106
  say validation_output, :cyan
116
107
 
117
108
  # 7. Check if container is running
@@ -119,19 +110,20 @@ module Kitsune
119
110
 
120
111
  if container_status.empty?
121
112
  say "โ–ถ๏ธ No running container. Running docker compose up...", :cyan
122
- ssh.exec!("cd #{docker_dir_remote} && docker compose up -d")
113
+ ssh.exec!("cd #{remote_dir} && docker compose up -d")
123
114
  else
124
115
  say "โš ๏ธ PostgreSQL container is already running.", :yellow
125
116
  if yes?("๐Ÿ” Recreate the container with updated configuration? [y/N]", :yellow)
126
117
  say "๐Ÿ”„ Recreating container...", :cyan
127
- ssh.exec!("cd #{docker_dir_remote} && docker compose down -v && docker compose up -d")
118
+ ssh.exec!("cd #{remote_dir} && docker compose down -v && docker compose up -d")
128
119
  else
129
120
  say "โฉ Keeping existing container.", :cyan
130
121
  end
131
122
  end
132
123
 
124
+ # 8. Check container status
133
125
  say "๐Ÿ“‹ Final container status (docker compose ps):", :cyan
134
- docker_ps_output = ssh.exec!("cd #{docker_dir_remote} && docker compose ps --format json")
126
+ docker_ps_output = ssh.exec!("cd #{remote_dir} && docker compose ps --format json")
135
127
 
136
128
  if docker_ps_output.nil? || docker_ps_output.strip.empty? || docker_ps_output.include?("no configuration file")
137
129
  say "โš ๏ธ docker compose ps returned no valid output.", :yellow
@@ -168,9 +160,13 @@ module Kitsune
168
160
  if healthcheck.include?("accepting connections")
169
161
  say "โœ… PostgreSQL is up and accepting connections! (attempt #{attempt})", :green
170
162
  success = true
163
+
164
+ database_url = build_database_url(filled_options, postgres_defaults)
165
+ say "๐Ÿ”— Your DATABASE_URL is:\t", :cyan
166
+ say database_url, :green
171
167
  break
172
168
  else
173
- say "โณ PostgreSQL not ready yet, retrying in 5 seconds... (#{attempt + 1}/#{max_attempts})", :yellow
169
+ say "โณ PostgreSQL not ready yet, retrying in 5 seconds... (#{attempt}/#{max_attempts})", :yellow
174
170
  sleep 5
175
171
  end
176
172
  end
@@ -181,7 +177,7 @@ module Kitsune
181
177
 
182
178
  # 10. Allow PostgreSQL port through firewall (ufw)
183
179
  say "๐Ÿ›ก๏ธ Configuring firewall to allow PostgreSQL (port #{postgres_defaults[:postgres_port]})...", :cyan
184
- firewall = <<~EOH
180
+ output = ssh.exec! <<~EOH
185
181
  if command -v ufw >/dev/null; then
186
182
  if ! sudo ufw status | grep -q "#{postgres_defaults[:postgres_port]}"; then
187
183
  sudo ufw allow #{postgres_defaults[:postgres_port]}
@@ -192,7 +188,9 @@ module Kitsune
192
188
  echo "โš ๏ธ ufw not found. Skipping firewall configuration."
193
189
  fi
194
190
  EOH
195
- ssh.exec!(firewall)
191
+ say output
192
+
193
+ say "โœ… PostgreSQL setup completed successfully!", :green
196
194
  end
197
195
 
198
196
  def perform_rollback(ssh, postgres_defaults)
@@ -227,9 +225,9 @@ module Kitsune
227
225
  end
228
226
 
229
227
  def upload_file(ssh, content, remote_path)
230
- escaped_content = Shellwords.escape(content)
228
+ escaped = Shellwords.escape(content)
231
229
  ssh.exec!("mkdir -p #{File.dirname(remote_path)}")
232
- ssh.exec!("echo #{escaped_content} > #{remote_path}")
230
+ ssh.exec!("echo #{escaped} > #{remote_path}")
233
231
  end
234
232
 
235
233
  def build_database_url(filled_options, postgres_defaults)
@@ -0,0 +1,241 @@
1
+ require "thor"
2
+ require "net/ssh"
3
+ require "fileutils"
4
+ require "shellwords"
5
+ require_relative "../defaults"
6
+ require_relative "../options_builder"
7
+ require "pry"
8
+ module Kitsune
9
+ module Kit
10
+ module Commands
11
+ class SetupRedisDocker < Thor
12
+ namespace "setup_redis_docker"
13
+
14
+ class_option :server_ip, aliases: "-s", required: true, desc: "Server IP address or hostname"
15
+ class_option :ssh_port, aliases: "-p", desc: "SSH port"
16
+ class_option :ssh_key_path, aliases: "-k", desc: "Path to SSH private key"
17
+
18
+ desc "create", "Setup Redis using Docker Compose on remote server"
19
+ def create
20
+ redis_defaults = Kitsune::Kit::Defaults.redis
21
+
22
+ if redis_defaults[:redis_password] == "secret"
23
+ say "โš ๏ธ Warning: You are using the default Redis password ('secret').", :yellow
24
+ if ENV.fetch("KIT_ENV", "development") == "production"
25
+ abort "โŒ Production environment requires a secure Redis password!"
26
+ else
27
+ say "๐Ÿ”’ Please change REDIS_PASSWORD in your .env if needed.", :yellow
28
+ end
29
+ end
30
+
31
+ filled_options = Kitsune::Kit::OptionsBuilder.build(
32
+ options,
33
+ required: [:server_ip],
34
+ defaults: Kitsune::Kit::Defaults.ssh
35
+ )
36
+
37
+ with_ssh_connection(filled_options) do |ssh|
38
+ perform_setup(ssh, redis_defaults, filled_options)
39
+ end
40
+ end
41
+
42
+ desc "rollback", "Remove Redis Docker setup from remote server"
43
+ def rollback
44
+ redis_defaults = Kitsune::Kit::Defaults.redis
45
+
46
+ filled_options = Kitsune::Kit::OptionsBuilder.build(
47
+ options,
48
+ required: [:server_ip],
49
+ defaults: Kitsune::Kit::Defaults.ssh
50
+ )
51
+
52
+ with_ssh_connection(filled_options) do |ssh|
53
+ perform_rollback(ssh, redis_defaults)
54
+ end
55
+ end
56
+
57
+ no_commands do
58
+ def with_ssh_connection(filled_options)
59
+ server = filled_options[:server_ip]
60
+ port = filled_options[:ssh_port]
61
+ key = File.expand_path(filled_options[:ssh_key_path])
62
+
63
+ say "๐Ÿ”‘ Connecting as deploy@#{server}:#{port}", :green
64
+ Net::SSH.start(server, "deploy", port: port, keys: [key], non_interactive: true, timeout: 5) do |ssh|
65
+ yield ssh
66
+ end
67
+ end
68
+
69
+ def perform_setup(ssh, redis_defaults, filled_options)
70
+ local_compose = ".kitsune/docker/redis.yml"
71
+ remote_dir = "$HOME/docker/redis"
72
+ compose_remote = "#{remote_dir}/docker-compose.yml"
73
+ env_remote = "#{remote_dir}/.env"
74
+ marker = "/usr/local/backups/setup_redis_docker.after"
75
+
76
+ abort "โŒ Missing #{local_compose}" unless File.exist?(local_compose)
77
+
78
+ # 1. Create base directory securely
79
+ ssh.exec!("mkdir -p #{remote_dir} && chmod 700 #{remote_dir}")
80
+
81
+ # 2. Upload docker-compose.yml
82
+ say "๐Ÿ“ฆ Uploading docker-compose.yml to #{remote_dir}", :cyan
83
+ upload_file(ssh, File.read(local_compose), compose_remote)
84
+
85
+ # 3. Create .env file for docker-compose based on redis_defaults
86
+ env_content = <<~ENVFILE
87
+ REDIS_PORT=#{redis_defaults[:redis_port]}
88
+ REDIS_PASSWORD=#{redis_defaults[:redis_password]}
89
+ ENVFILE
90
+ upload_file(ssh, env_content, env_remote)
91
+
92
+ # 4. Secure file permissions
93
+ ssh.exec!("chmod 600 #{compose_remote} #{env_remote}")
94
+
95
+ # 5. Create a backup marker
96
+ ssh.exec!("sudo mkdir -p /usr/local/backups && sudo touch #{marker}")
97
+
98
+ # 6. Validate docker-compose.yml
99
+ say "๐Ÿ” Validating docker-compose.yml...", :cyan
100
+ validation_output = ssh.exec!("cd #{remote_dir} && docker compose config")
101
+ say validation_output, :cyan
102
+
103
+ # 7. Check if container is running
104
+ container_status = ssh.exec!("docker ps --filter 'name=redis' --format '{{.Status}}'").strip
105
+
106
+ if container_status.empty?
107
+ say "โ–ถ๏ธ No running container. Running docker compose up...", :cyan
108
+ ssh.exec!("cd #{remote_dir} && docker compose up -d")
109
+ else
110
+ say "โš ๏ธ Redis container is already running.", :yellow
111
+ if yes?("๐Ÿ” Recreate the container with updated configuration? [y/N]", :yellow)
112
+ say "๐Ÿ”„ Recreating container...", :cyan
113
+ ssh.exec!("cd #{remote_dir} && docker compose down -v && docker compose up -d")
114
+ else
115
+ say "โฉ Keeping existing container.", :cyan
116
+ end
117
+ end
118
+
119
+ # 8. Check container status
120
+ say "๐Ÿ“‹ Final container status (docker compose ps):", :cyan
121
+ docker_ps_output = ssh.exec!("cd #{remote_dir} && docker compose ps --format json")
122
+
123
+ if docker_ps_output.nil? || docker_ps_output.strip.empty? || docker_ps_output.include?("no configuration file")
124
+ say "โš ๏ธ docker compose ps returned no valid output.", :yellow
125
+ else
126
+ begin
127
+ services = JSON.parse(docker_ps_output)
128
+ services = [services] if services.is_a?(Hash)
129
+
130
+ redis = services.find { |svc| svc["Service"] == "redis" }
131
+ status = redis && redis["State"]
132
+ health = redis && redis["Health"]
133
+
134
+ if (status == "running" && health == "healthy") || (health == "healthy")
135
+ say "โœ… Redis container is running and healthy.", :green
136
+ else
137
+ say "โš ๏ธ Redis container is not healthy yet.", :yellow
138
+ end
139
+ rescue JSON::ParserError => e
140
+ say "๐Ÿšจ Failed to parse docker compose ps output as JSON: #{e.message}", :red
141
+ end
142
+ end
143
+
144
+ # 9. Check Redis readiness with retries
145
+ say "๐Ÿ” Checking Redis health with retries...", :cyan
146
+
147
+ max_attempts = 10
148
+ attempt = 0
149
+ success = false
150
+
151
+ while attempt < max_attempts
152
+ attempt += 1
153
+ healthcheck = ssh.exec!("docker exec $(docker ps -qf name=redis) redis-cli --no-auth-warning -a #{redis_defaults[:redis_password]} PING")
154
+
155
+ if healthcheck.strip == "PONG"
156
+ say "โœ… Redis is up and responding to PING! (attempt #{attempt})", :green
157
+ success = true
158
+
159
+ redis_url = build_redis_url(filled_options, redis_defaults)
160
+ say "๐Ÿ”— Your REDIS_URL is:\t", :cyan
161
+ say redis_url, :green
162
+ break
163
+ else
164
+ say "โณ Redis not ready yet, retrying in 5 seconds... (#{attempt}/#{max_attempts})", :yellow
165
+ sleep 5
166
+ end
167
+ end
168
+
169
+ unless success
170
+ say "โŒ Redis did not become ready after #{max_attempts} attempts.", :red
171
+ end
172
+
173
+ # 10. Allow Redis port through firewall (ufw)
174
+ say "๐Ÿ›ก๏ธ Configuring firewall to allow Redis (port #{redis_defaults[:redis_port]})...", :cyan
175
+ output = ssh.exec! <<~EOH
176
+ if command -v ufw >/dev/null; then
177
+ if ! sudo ufw status | grep -q "#{redis_defaults[:redis_port]}"; then
178
+ sudo ufw allow #{redis_defaults[:redis_port]}
179
+ else
180
+ echo "๐Ÿ’ก Port #{redis_defaults[:redis_port]} is already allowed in ufw."
181
+ fi
182
+ else
183
+ echo "โš ๏ธ ufw not found. Skipping firewall configuration."
184
+ fi
185
+ EOH
186
+ say output
187
+
188
+ say "โœ… Redis setup completed successfully!", :green
189
+ end
190
+
191
+ def perform_rollback(ssh, defaults)
192
+ output = ssh.exec! <<~EOH
193
+ set -e
194
+
195
+ BASE_DIR="$HOME/docker/redis"
196
+ BACKUP_DIR="/usr/local/backups"
197
+ SCRIPT_ID="setup_redis_docker"
198
+ AFTER_FILE="${BACKUP_DIR}/${SCRIPT_ID}.after"
199
+
200
+ if [ -f "$AFTER_FILE" ]; then
201
+ echo "๐Ÿ” Stopping and removing docker containers..."
202
+ cd "$BASE_DIR"
203
+ docker compose down -v || true
204
+
205
+ echo "๐Ÿงน Cleaning up files..."
206
+ rm -rf "$BASE_DIR"
207
+ sudo rm -f "$AFTER_FILE"
208
+
209
+ if command -v ufw >/dev/null; then
210
+ echo "๐Ÿ›ก๏ธ Removing Redis port from firewall..."
211
+ sudo ufw delete allow #{defaults[:redis_port]} || true
212
+ fi
213
+ else
214
+ echo "๐Ÿ’ก Nothing to rollback"
215
+ fi
216
+
217
+ echo "โœ… Rollback completed"
218
+ EOH
219
+
220
+ say output
221
+ end
222
+
223
+
224
+ def upload_file(ssh, content, remote_path)
225
+ escaped = Shellwords.escape(content)
226
+ ssh.exec!("mkdir -p #{File.dirname(remote_path)}")
227
+ ssh.exec!("echo #{escaped} > #{remote_path}")
228
+ end
229
+
230
+ def build_redis_url(filled_options, redis_defaults)
231
+ password = redis_defaults[:redis_password]
232
+ host = filled_options[:server_ip]
233
+ port = redis_defaults[:redis_port]
234
+
235
+ "redis://:#{password}@#{host}:#{port}/0"
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
241
+ end
@@ -19,7 +19,7 @@ module Kitsune
19
19
  user: "postgres",
20
20
  password: "secret",
21
21
  port: "5432",
22
- image: "postgres:15"
22
+ image: "postgres:17"
23
23
  }.freeze
24
24
 
25
25
  SYSTEM = {
@@ -32,6 +32,11 @@ module Kitsune
32
32
  enable_do_metrics: true
33
33
  }.freeze
34
34
 
35
+ REDIS = {
36
+ port: "6379",
37
+ password: "redis:7.2"
38
+ }.freeze
39
+
35
40
  def self.infra
36
41
  {
37
42
  droplet_name: ENV.fetch('DROPLET_NAME', DROPLET[:droplet_name]),
@@ -62,6 +67,13 @@ module Kitsune
62
67
  }
63
68
  end
64
69
 
70
+ def self.redis
71
+ {
72
+ redis_port: ENV.fetch("REDIS_PORT", REDIS[:port]),
73
+ redis_password: ENV.fetch("REDIS_PASSWORD", REDIS[:password])
74
+ }
75
+ end
76
+
65
77
  def self.system
66
78
  {
67
79
  swap_size_gb: ENV.fetch("SWAP_SIZE_GB", SYSTEM[:swap_size_gb]).to_i,
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Kitsune
4
4
  module Kit
5
- VERSION = "0.2.1"
5
+ VERSION = "0.3.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitsune-kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Omar Herrera
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-02 00:00:00.000000000 Z
11
+ date: 2025-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: net-ssh
@@ -184,6 +184,7 @@ files:
184
184
  - kitsune-kit-logo.jpg
185
185
  - lib/kitsune/blueprints/.env.template
186
186
  - lib/kitsune/blueprints/docker/postgres.yml
187
+ - lib/kitsune/blueprints/docker/redis.yml
187
188
  - lib/kitsune/blueprints/kit.env.template
188
189
  - lib/kitsune/kit.rb
189
190
  - lib/kitsune/kit/cli.rb
@@ -197,6 +198,7 @@ files:
197
198
  - lib/kitsune/kit/commands/setup_docker_prereqs.rb
198
199
  - lib/kitsune/kit/commands/setup_firewall.rb
199
200
  - lib/kitsune/kit/commands/setup_postgres_docker.rb
201
+ - lib/kitsune/kit/commands/setup_redis_docker.rb
200
202
  - lib/kitsune/kit/commands/setup_swap.rb
201
203
  - lib/kitsune/kit/commands/setup_unattended.rb
202
204
  - lib/kitsune/kit/commands/setup_user.rb