kaiser 0.4.5 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b038487b21d1842c497c567c1b7f5bfcd15113f4099106f3de2d59fbbd1151c9
4
- data.tar.gz: 7177b78736ccef59a0b4f4c0d2cfd0902cb4db1f5c235e9ed9eb8e6424ff6039
3
+ metadata.gz: 6923e91422d9639f4a595188c2cecc59e76634d01d738113caa52b877bd65ed7
4
+ data.tar.gz: 8014fb2b25df573937ed6529d068bc3b4d8aee0c1079703d7ecea871088e2df2
5
5
  SHA512:
6
- metadata.gz: deeb309b718a0bc5a53c108da2e561096deaa05fbf49433c6253c38b40435283e8dc53ac6bd122fe6726176f94e2f5823476805ddc50ba37a6c1b46ef9b3d8fb
7
- data.tar.gz: b9b5a6bd7ee1e163bbb1ff1ea00fb7112efa47bf8ddb7f5ba1a5c4f9a456cfb5b7475da68bfcbc15889774392b1b7b1c6044ca7ca6f48430b30a2dfe863e0f95
6
+ metadata.gz: 6cd4c933744c44dca6dcb34f0f17e7379f7776e7a12d277606fe71fb213ad456fbd32357c777e58b61cb4928e3fcff0a815c7efbfd99e2162bdd9c1fdc1202ad
7
+ data.tar.gz: 056070423d8763378e279765c5d91dd9668c82600372e76fc8ed417baef0d834d38fd60f10c66d45f16a01395034497b210a03300b7d990bc413d32ce77aca49
data/README.md CHANGED
@@ -97,6 +97,95 @@ open http://myapp.lvh.me
97
97
 
98
98
  And enjoy previewing your app!
99
99
 
100
+ #### Anatomy of a Kaiserfile
101
+
102
+ A Kaiserfile is made up of statements, which are different commands followed by some parameters. Each command is just a ruby method so you can call it that way. Only the `dockerfile` command is required. All the other commands are either not required or have defaults.
103
+
104
+ - `plugin` - Takes 1 parameter: the name of the plugin you wish to use in this Kaiserfile.
105
+
106
+ ```ruby
107
+ # Example
108
+ plugin :git_submodule
109
+ ```
110
+
111
+ See further below to find available plugins and their usage
112
+
113
+ - `dockerfile` - This command is always required. Takes 1 parameter: the name of the Dockerfile you want to use with this Kaiserfile. You only need to use this command once. Using it multiple times will simply cause the last command to be used. It takes relative paths and the paths are relative to where you run Kaiser.
114
+
115
+ ```ruby
116
+ # Example
117
+ dockerfile 'Dockerfile'
118
+ ```
119
+
120
+ - `service` - This command is optional. Use it to define additional containers that should be set up along with your environment,. You can use it multiple times to define multiple services. It takes multiple parameters, a name parameter which is required and optional parameters.
121
+
122
+ ```ruby
123
+ # example that sets up a redis server for your app
124
+ service 'redis'
125
+ ```
126
+
127
+ The following parameters are allowed for this command:
128
+ - image
129
+
130
+ ```ruby
131
+ # example that tells it to use the redis server with the alpine tag from 'myrepo'
132
+ service 'redis', image: 'myrepo/redis:alpine'
133
+ ```
134
+
135
+ - `attach_mount` - Takes 2 parameters: The first parameter is the relative path of a folder or a file outside the container and the second parameter is its absolute path inside the container. This is only used when `kaiser attach` or `kaiser up -a` is used. This will mount the file or folder inside the container and sync their contents. If the file you specified does not exist, Kaiser will create a folder where you specify it and then mount that folder inside the container. You can specify as many of these as you want.
136
+
137
+ ```ruby
138
+ # Example to mount the `app` directory into the container's `/srv/files/app`
139
+ attach_mount 'app', '/srv/files/app'
140
+ ```
141
+
142
+ - `expose` - Takes 1 parameter: The port of the server running inside the container. This port is not exposed on the host, so it will not occupy a port on the computer you run kaiser on. Instead, Kaiser will select a random port on the host computer to forward traffic to and from. You can only use this statement once. If you have multiple of these statements the last one will be used.
143
+
144
+ ```ruby
145
+ # Example to expose the port 3636
146
+ expose 3636
147
+ ```
148
+
149
+ - `app_params` - Takes 1 parameter: A string of parameters to the `docker run` command to add custom environment variables with. Please refer to the docker documentation to see what kinds of parameters you can pass to the `docker run` command. By default this is just an empty string. You can only pass one of these. Any newline characters in the string will be converted into spaces.
150
+
151
+ ```ruby
152
+ # Example
153
+ app_params '-e INTERACTIVE=no'
154
+ ```
155
+
156
+ - `type` - Takes 1 parameter: Right now the only parameter it can take is `:http`. If this parameter is specified, kaiser will poll the application until it receives a 200 status code before it closes when you use `kaiser up` If it doesn't it will close with a status code of 1.
157
+
158
+ ```ruby
159
+ # Example
160
+ type :http
161
+ ```
162
+
163
+ - `db_reset_command` - Takes 1 parameter: A command to reset the database. This command is optional. By default this parameter is `echo "no db to reset"`. You can only specify one of these. If you have multiple of these commands only the last one will be used.
164
+
165
+ ```ruby
166
+ # Example if running this command drops the db and recreates it.
167
+ db_reset_command 'rake db:reset'
168
+ ```
169
+
170
+ - `db` - Takes 1 parameter in the form of a hash. The default value of the hash is as follows:
171
+
172
+ (You do not have to use this strictly, see the Database Plugin below to see an easier way to include MySQL and Postgres in your environment)
173
+
174
+ ```ruby
175
+ # Default settings
176
+ {
177
+ image: 'alpine',
178
+ port: 1234,
179
+ data_dir: '/tmp/data',
180
+ params: '',
181
+ commands: 'echo "no db"',
182
+ waitscript: 'echo "no dbwait"',
183
+ waitscript_params: ''
184
+ }
185
+ ```
186
+
187
+ You can use this to customize the database that you wish to use with your server.
188
+
100
189
  ### Alternative Kaiserfile
101
190
 
102
191
  If you want change your dev environment for a project, but don't want to overwrite the project's Kaiserfile/Dockerfile,
@@ -258,6 +347,59 @@ kaiser up
258
347
 
259
348
  Again for changes to take effect.
260
349
 
350
+ ## Plugins
351
+
352
+ Kaiser has a plugin system that adds commands to the Kaiserfile to help improve your workflow. Below are a list of built-in plugins that come with Kaiser.
353
+
354
+ ### Git Submodules Plugin
355
+
356
+ This plugin ensures that any submodules your repo has are checked out. If they are not, it will cause Kaiser to exit with a status code of 1.
357
+
358
+ Usage:
359
+
360
+ ```ruby
361
+ plugin :git_submodule
362
+ ```
363
+
364
+ That's all you need!
365
+
366
+ ### Database Plugin
367
+
368
+ This plugin allows you to specify well known DBs (MySQL and PostgresSQL) with default values that work generally. You can customize your database however you want it for your own project.
369
+
370
+ Usage:
371
+
372
+ ```ruby
373
+ # Simplest usage
374
+ plugin :database
375
+
376
+ def_db :mysql
377
+ ```
378
+
379
+ If for example you wish to use a different root password, simply go
380
+
381
+ ```ruby
382
+ plugin :database
383
+
384
+ def_db mysql: { root_password: 'extremesecret' }
385
+ ```
386
+
387
+ Sometimes you want to use a specific version for testing. You can set up the version by going
388
+
389
+ ```ruby
390
+ plugin :database
391
+
392
+ def_db postgres: { version: '9.4' }
393
+ ```
394
+
395
+ You can also pass startup parameters to your database server:
396
+
397
+ ```ruby
398
+ plugin :database
399
+
400
+ def_db mysql: { parameters: '--verbose' }
401
+ ```
402
+
261
403
  ## Development
262
404
 
263
405
  After checking out the repo, run `bundle install` to install dependencies. Then, run `rake spec` to run the tests.
@@ -275,7 +417,3 @@ The gem is available as open source under the terms of the [MIT License](https:/
275
417
  ## Code of Conduct
276
418
 
277
419
  Everyone interacting in the Kaiser project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/degica/kaiser/blob/master/CODE_OF_CONDUCT.md).
278
-
279
- ## Contributors
280
-
281
- - Guga Katsiashvili (provided the rubygem)
@@ -27,7 +27,8 @@ require 'kaiser/cmds/set'
27
27
  require 'kaiser/cmds/root'
28
28
 
29
29
  require 'kaiser/plugin'
30
- require 'kaiser/plugins/git_submodule'
30
+
31
+ require 'kaiser/service'
31
32
 
32
33
  # Kaiser
33
34
  module Kaiser
@@ -17,6 +17,8 @@ module Kaiser
17
17
  @config = Config.config
18
18
  @out = Config.out
19
19
  @info_out = Config.info_out
20
+
21
+ @kaiserfile.validate!
20
22
  end
21
23
 
22
24
  # At first I did this in the constructor but the problem with that is Optimist
@@ -91,15 +93,30 @@ module Kaiser
91
93
  output
92
94
  end
93
95
 
94
- def down
95
- stop_db
96
- stop_app
97
- delete_db_volume
98
- end
99
-
100
96
  def stop_app
101
97
  Config.info_out.puts 'Stopping application'
102
98
  killrm app_container_name
99
+ stop_services
100
+ end
101
+
102
+ def start_services
103
+ services.each do |service|
104
+ Config.info_out.puts "Starting service: #{service.name}"
105
+ run_if_dead(
106
+ service.shared_name,
107
+ "docker run -d
108
+ --name #{service.shared_name}
109
+ --network #{Config.config[:networkname]}
110
+ #{service.image}"
111
+ )
112
+ end
113
+ end
114
+
115
+ def stop_services
116
+ services.each do |service|
117
+ Config.info_out.puts "Stopping service: #{service.name}"
118
+ killrm service.shared_name
119
+ end
103
120
  end
104
121
 
105
122
  private
@@ -236,6 +253,8 @@ module Kaiser
236
253
  end
237
254
 
238
255
  def start_app
256
+ start_services
257
+
239
258
  Config.info_out.puts 'Starting up application'
240
259
  killrm app_container_name
241
260
  CommandRunner.run! Config.out, "docker run -d
@@ -351,6 +370,10 @@ module Kaiser
351
370
  Config.config[:networkname]
352
371
  end
353
372
 
373
+ def services
374
+ @services ||= Config.kaiserfile.services.map { |name, info| Service.new(envname, name, info) }
375
+ end
376
+
354
377
  def db_port
355
378
  Config.config[:envs][envname][:db_port]
356
379
  end
@@ -12,7 +12,9 @@ module Kaiser
12
12
  end
13
13
 
14
14
  def execute(_opts)
15
- down
15
+ stop_db
16
+ stop_app
17
+ delete_db_volume
16
18
  end
17
19
  end
18
20
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kaiser
4
+ module Databases
5
+ class Mysql
6
+ def initialize(options)
7
+ @options = options
8
+ end
9
+
10
+ def options_hash
11
+ testpass = @options[:root_password] || 'testpassword'
12
+ parameters = @options[:parameters] || ''
13
+ port = @options[:port] || 3306
14
+
15
+ {
16
+ port: port,
17
+ data_dir: '/var/lib/mysql',
18
+ params: "-e MYSQL_ROOT_PASSWORD=#{testpass}",
19
+ commands: parameters,
20
+ waitscript_params: "
21
+ -e MYSQL_ADDR=<%= db_container_name %>
22
+ -e MYSQL_PORT=#{port}
23
+ -e MYSQL_ROOT_PASSWORD=#{testpass}",
24
+ waitscript: <<~SCRIPT
25
+ #!/bin/bash
26
+
27
+ echo "Waiting for mysql to start."
28
+ until mysql -h"$MYSQL_ADDR" -P"$MYSQL_PORT" -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SELECT 1"
29
+ do
30
+ printf "."
31
+ sleep 1
32
+ done
33
+
34
+ echo -e "\nmysql started."
35
+ SCRIPT
36
+ }
37
+ end
38
+
39
+ def image_name
40
+ version = @options[:version] || '5.6'
41
+ "mysql:#{version}"
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kaiser
4
+ module Databases
5
+ class Postgres
6
+ def initialize(options)
7
+ @options = options
8
+ end
9
+
10
+ def options_hash
11
+ testpass = @options[:root_password] || 'testpassword'
12
+ parameters = @options[:parameters] || ''
13
+ port = @options[:port] || 3306
14
+
15
+ {
16
+ port: port,
17
+ data_dir: '/var/lib/postgresql/data',
18
+ params: "-e POSTGRES_PASSWORD=#{testpass}",
19
+ commands: parameters,
20
+ waitscript_params: "
21
+ -e PG_HOST=<%= db_container_name %>
22
+ -e PG_USER=postgres
23
+ -e PGPASSWORD=#{testpass}
24
+ -e PG_DATABASE=postgres",
25
+ waitscript: <<~SCRIPT
26
+ #!/bin/sh
27
+
28
+ RETRIES=5
29
+
30
+ until psql -h $PG_HOST -U $PG_USER -d $PG_DATABASE -c "select 1" > /dev/null 2>&1 || [ $RETRIES -eq 0 ]; do
31
+ echo "Waiting for postgres server, $((RETRIES--)) remaining attempts..."
32
+ sleep 1
33
+ done
34
+ SCRIPT
35
+ }
36
+ end
37
+
38
+ def image_name
39
+ version = @options[:version] || 'alpine'
40
+ "postgres:#{version}"
41
+ end
42
+ end
43
+ end
44
+ end
@@ -9,20 +9,37 @@ module Kaiser
9
9
  :port,
10
10
  :database_reset_command,
11
11
  :attach_mounts,
12
- :server_type
12
+ :server_type,
13
+ :services
13
14
 
14
15
  def initialize(filename)
15
16
  Optimist.die 'No Kaiserfile in current directory' unless File.exist? filename
16
17
 
17
- @databases = {}
18
+ @database = {
19
+ image: 'alpine',
20
+ port: 1234,
21
+ data_dir: '/tmp/data',
22
+ params: '',
23
+ commands: 'echo "no db"',
24
+ waitscript: 'echo "no dbwait"',
25
+ waitscript_params: ''
26
+ }
18
27
  @attach_mounts = []
19
28
  @params_array = []
20
29
  @server_type = :unknown
30
+ @database_reset_command = 'echo "no db to reset"'
31
+ @port = 1234
32
+ @services = {}
21
33
 
22
34
  instance_eval File.read(filename), filename
23
35
  end
24
36
 
37
+ def validate!
38
+ raise 'No dockerfile specified.' if @docker_file_contents.nil?
39
+ end
40
+
25
41
  def plugin(name)
42
+ require "kaiser/plugins/#{name}"
26
43
  raise "Plugin #{name} is not loaded." unless Plugin.loaded?(name)
27
44
 
28
45
  Plugin.all_plugins[name].new(self).on_init
@@ -76,5 +93,11 @@ module Kaiser
76
93
 
77
94
  @server_type = value
78
95
  end
96
+
97
+ def service(name, image: name)
98
+ raise "duplicate service #{name.inspect}" if @services.key?(name)
99
+
100
+ @services[name] = { image: image }
101
+ end
79
102
  end
80
103
  end
@@ -56,3 +56,9 @@ module Kaiser
56
56
  end
57
57
  end
58
58
  end
59
+
60
+ # Little stub to initialize the namespace
61
+ module Kaiser
62
+ module Plugins
63
+ end
64
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/inflector'
4
+
5
+ module Kaiser
6
+ module Plugins
7
+ class Database < Plugin
8
+ def on_init
9
+ @kaiserfile.define_singleton_method :def_db do |*args|
10
+ args[0] = { args.first => {} } unless args.first.is_a? Hash
11
+
12
+ option = args.first
13
+
14
+ driver_name = option.keys.first.to_s
15
+
16
+ begin
17
+ require "kaiser/databases/#{driver_name}"
18
+ rescue LoadError
19
+ raise "Unknown database '#{driver_name}'"
20
+ end
21
+
22
+ driver_class = Kaiser::Databases.const_get(driver_name.camelize)
23
+ db_driver = driver_class.new(option.values.first)
24
+
25
+ db(db_driver.image_name, **db_driver.options_hash)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,18 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kaiser
4
- class GitSubmodule < Plugin
5
- def on_init
6
- `git submodule status`.lines.each do |line|
7
- # The git-submodule man page says uninitialized submodules are prefixed with a -
8
- # but I found this unreliable. While testing I pressed Control-C in the middle of
9
- # the update command so some submodule would be initialized and others wouldn't.
10
- # After that, the status command had removed the - for every submodule.
11
- # Therefore we just check if there's files in the directory instead.
12
- dir = line.strip.split(' ')[1]
13
- if !Dir.exist?(dir) || Dir.empty?(dir) # rubocop:disable Style/Next
14
- puts "Found uninitialized git submodule '#{dir}'"
15
- system 'git submodule update --init --recursive'
4
+ module Plugins
5
+ class GitSubmodule < Plugin
6
+ def on_init
7
+ `git submodule status`.lines.each do |line|
8
+ # The git-submodule man page says uninitialized submodules are prefixed with a -
9
+ # but I found this unreliable. While testing I pressed Control-C in the middle of
10
+ # the update command so some submodule would be initialized and others wouldn't.
11
+ # After that, the status command had removed the - for every submodule.
12
+ # Therefore we just check if there's files in the directory instead.
13
+ dir = line.strip.split(' ')[1]
14
+ if !Dir.exist?(dir) || Dir.empty?(dir) # rubocop:disable Style/Next
15
+ puts "Found uninitialized git submodule '#{dir}'"
16
+ puts "please run 'git submodule update --init --recursive'"
17
+ exit 1
18
+ end
16
19
  end
17
20
  end
18
21
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kaiser
4
+ # This class describes an app-specific service
5
+ class Service
6
+ attr_reader :name
7
+
8
+ def initialize(envname, name, service_info)
9
+ @envname = envname
10
+ @name = name
11
+ @service_info = service_info
12
+ end
13
+
14
+ def shared_name
15
+ "#{@envname}-#{name}"
16
+ end
17
+
18
+ def image
19
+ @service_info[:image]
20
+ end
21
+ end
22
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kaiser
4
- VERSION = '0.4.5'
4
+ VERSION = '0.5.1'
5
5
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kaiser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Siaw
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-18 00:00:00.000000000 Z
11
+ date: 2020-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: optimist
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -25,19 +25,33 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: aruba
28
+ name: optimist
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
- type: :development
34
+ type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: aruba
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.14.6
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.14.6
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: aruba-rspec
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +80,20 @@ dependencies:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
82
  version: '4.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry-byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
69
97
  - !ruby/object:Gem::Dependency
70
98
  name: rake
71
99
  requirement: !ruby/object:Gem::Requirement
@@ -139,12 +167,16 @@ files:
139
167
  - lib/kaiser/cmds/up.rb
140
168
  - lib/kaiser/command_runner.rb
141
169
  - lib/kaiser/config.rb
170
+ - lib/kaiser/databases/mysql.rb
171
+ - lib/kaiser/databases/postgres.rb
142
172
  - lib/kaiser/docker_control.rb
143
173
  - lib/kaiser/dotter.rb
144
174
  - lib/kaiser/error.rb
145
175
  - lib/kaiser/kaiserfile.rb
146
176
  - lib/kaiser/plugin.rb
177
+ - lib/kaiser/plugins/database.rb
147
178
  - lib/kaiser/plugins/git_submodule.rb
179
+ - lib/kaiser/service.rb
148
180
  - lib/kaiser/version.rb
149
181
  homepage: https://github.com/kaiser
150
182
  licenses: