minke 0.16.0 → 1.0.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.
Files changed (42) hide show
  1. checksums.yaml +8 -8
  2. data/.codeclimate.yml +7 -0
  3. data/.gitignore +1 -0
  4. data/.ruby-version +1 -1
  5. data/.travis.yml +4 -1
  6. data/Gemfile +5 -0
  7. data/Guardfile +70 -0
  8. data/README.md +12 -9
  9. data/bin/minke +48 -0
  10. data/examples/config_go.yml +44 -25
  11. data/lib/minke/config/config.rb +326 -0
  12. data/lib/minke/config/reader.rb +94 -0
  13. data/lib/minke/docker/docker_compose.rb +53 -0
  14. data/lib/minke/docker/docker_runner.rb +123 -0
  15. data/lib/minke/docker/service_discovery.rb +24 -0
  16. data/lib/minke/docker/system_runner.rb +16 -0
  17. data/lib/minke/generators/config.rb +106 -0
  18. data/lib/minke/generators/config_processor.rb +47 -0
  19. data/lib/minke/generators/config_variables.rb +23 -0
  20. data/lib/minke/generators/processor.rb +131 -0
  21. data/lib/minke/generators/register.rb +19 -0
  22. data/lib/minke/helpers/helper.rb +68 -0
  23. data/lib/minke/rake/app.rake +50 -198
  24. data/lib/minke/rake/config.rake +1 -5
  25. data/lib/minke/rake/docker.rake +7 -5
  26. data/lib/minke/tasks/build.rb +17 -0
  27. data/lib/minke/tasks/build_image.rb +13 -0
  28. data/lib/minke/tasks/cucumber.rb +34 -0
  29. data/lib/minke/tasks/fetch.rb +16 -0
  30. data/lib/minke/tasks/push.rb +22 -0
  31. data/lib/minke/tasks/run.rb +23 -0
  32. data/lib/minke/tasks/task.rb +107 -0
  33. data/lib/minke/tasks/test.rb +17 -0
  34. data/lib/minke/version.rb +1 -1
  35. data/lib/minke.rb +33 -9
  36. data/minke.gemspec +16 -11
  37. metadata +84 -9
  38. data/lib/minke/commands/go.rb +0 -27
  39. data/lib/minke/commands/swift.rb +0 -32
  40. data/lib/minke/docker.rb +0 -122
  41. data/lib/minke/docker_compose.rb +0 -31
  42. data/lib/minke/helpers.rb +0 -56
@@ -0,0 +1,68 @@
1
+ module Minke
2
+ module Helpers
3
+ class Helper
4
+ ##
5
+ # copy assets from one location to another
6
+ def copy_assets from, to
7
+ directory = to
8
+ if File.directory?(to)
9
+ directory = File.dirname(to)
10
+ end
11
+
12
+ Dir.mkdir directory unless Dir.exist? to
13
+ FileUtils.cp from, to
14
+ end
15
+
16
+ ##
17
+ # invoke a rake task
18
+ def invoke_task task
19
+ Rake::Task[task].invoke
20
+ end
21
+
22
+ def load_consul_data server, config_file
23
+ wait_for_HTTPOK "#{server}/v1/status/leader", 0, 1
24
+ loader = ConsulLoader::Loader.new(ConsulLoader::ConfigParser.new)
25
+ puts config_file
26
+ loader.load_config config_file, server
27
+ end
28
+
29
+ def execute_shell_command command
30
+ puts `#{command}`
31
+ $?.exitstatus
32
+ end
33
+
34
+ def fatal_error message
35
+ abort message
36
+ end
37
+
38
+ ##
39
+ # waits until a 200 response is received from the given url
40
+ def wait_for_HTTPOK url, count, successes = 0
41
+ begin
42
+ response = RestClient.send("get", url)
43
+ rescue
44
+
45
+ end
46
+
47
+ if response == nil || !response.code.to_i == 200
48
+ puts "Waiting for server #{url} to start"
49
+ sleep 1
50
+ if count < 180
51
+ wait_for_HTTPOK url, count + 1
52
+ else
53
+ raise 'Server failed to start'
54
+ end
55
+ else
56
+ if successes > 0
57
+ puts "Server: #{url} passed health check, #{successes} checks to go..."
58
+ sleep 1
59
+ wait_for_HTTPOK url, count + 1, successes - 1
60
+ else
61
+ puts "Server: #{url} healthy"
62
+ end
63
+ end
64
+ end
65
+
66
+ end
67
+ end
68
+ end
@@ -1,228 +1,80 @@
1
1
  namespace :app do
2
2
 
3
- desc "get dependent packages"
4
- task :get => ['config:set_docker_env', 'config:load_config', 'docker:fetch_images'] do
5
- config = Minke::Helpers.config
6
-
7
- if config[:build_config][:build][:get] != nil
8
- puts "## Get dependent packages"
9
- config[:build_config][:build][:get].each do |command|
10
- begin
11
- container, ret = Minke::Docker.create_and_run_container config, command
12
- ensure
13
- Minke::Docker.delete_container container
14
- end
15
- end
16
- puts ""
17
- end
3
+ desc "fetch dependent packages"
4
+ task :fetch => ['config:set_docker_env', 'docker:fetch_images'] do
5
+ create_dependencies
6
+ runner = Minke::Tasks::Fetch.new @config, :fetch, @generator_config, @docker_runner, @docker_compose_factory, @logger, @helper
7
+ runner.run
18
8
  end
19
9
 
20
10
  desc "build application"
21
- task :build => [:get] do
22
- puts "## Build for Linux"
23
- config = Minke::Helpers.config
24
-
25
- # do we need to build a custom build container
26
- if config['docker']['build'] && config['docker']['build']['docker_file'] != nil
27
- puts "## Building custom docker image"
28
-
29
- docker_file = config['docker']['build']['docker_file']
30
- image_name = config['application_name'] + "-buildimage"
31
-
32
- Docker.options = {:read_timeout => 6200}
33
- image = Docker::Image.build_from_dir docker_file, {:t => image_name}
34
- config[:build_config][:docker][:image] = image_name
35
- end
36
-
37
- if config['docker']['build'] && config['docker']['build']['image'] != nil
38
- config[:build_config][:docker][:image] = config['docker']['build']['image']
39
- end
40
-
41
- if config['build'] != nil && config['build']['before'] != nil
42
- config['build']['before'].each do |task|
43
- puts "## Running before build task: #{task}"
44
- Rake::Task[task].invoke
45
-
46
- puts ""
47
- end
48
- end
49
-
50
- config[:build_config][:build][:build].each do |command|
51
- begin
52
- # Build application
53
- container, ret = Minke::Docker.create_and_run_container config, command
54
- raise Exception, 'Error running command' unless ret == 0
55
- ensure
56
- Minke::Docker.delete_container container
57
- end
58
- end
59
-
60
- puts ""
11
+ task :build => [:fetch] do
12
+ create_dependencies
13
+ runner = Minke::Tasks::Build.new @config, :build, @generator_config, @docker_runner, @docker_compose_factory, @logger, @helper
14
+ runner.run
61
15
  end
62
16
 
63
17
  desc "run unit tests"
64
18
  task :test => [:build] do
65
- config = Minke::Helpers.config
66
-
67
- if config['test'] != nil && config['test']['before'] != nil
68
- config['test']['before'].each do |task|
69
- puts "## Running before test task: #{task}"
70
- Rake::Task[task].invoke
71
-
72
- puts ""
73
- end
74
- end
75
-
76
- puts "## Test application"
77
- config[:build_config][:build][:test].each do |command|
78
- begin
79
- # Test application
80
- container, ret = Minke::Docker.create_and_run_container config, command
81
- raise Exception, 'Error running command' unless ret == 0
82
- ensure
83
- Minke::Docker.delete_container container
84
- end
85
- end
86
-
87
- puts ""
88
- end
89
-
90
- task :copy_assets do
91
- puts "## Copy assets"
92
-
93
- config = Minke::Helpers.config
94
-
95
- if config['after_build'] != nil && config['after_build']['copy_assets'] != nil
96
- Minke::Helpers.copy_files config['after_build']['copy_assets']
97
- end
98
-
99
- puts ""
19
+ create_dependencies
20
+ runner = Minke::Tasks::Test.new @config, :test, @generator_config, @docker_runner, @docker_compose_factory, @logger, @helper
21
+ runner.run
100
22
  end
101
23
 
102
24
  desc "build Docker image for application"
103
- task :build_server => [:test, :copy_assets] do
104
- config = Minke::Helpers.config
105
-
106
- puts "## Building Docker image"
107
-
108
- Docker.options = {:read_timeout => 6200}
109
- image = Docker::Image.build_from_dir config['docker']['docker_file'], {:t => config['application_name']}
110
-
111
- puts ""
25
+ task :build_image => [:test] do
26
+ create_dependencies
27
+ runner = Minke::Tasks::BuildImage.new @config, :test, @generator_config, @docker_runner, @docker_compose_factory, @logger, @helper
28
+ runner.run
112
29
  end
113
30
 
114
31
  desc "run application with Docker Compose"
115
- task :run => ['config:set_docker_env', 'config:load_config'] do
116
- puts "## Run application with docker compose"
117
-
118
- config = Minke::Helpers.config
119
-
120
- if config['run']['docker'] != nil && config['run']['docker']['compose_file'] != nil
121
- config_file = config['run']['docker']['compose_file']
122
- else
123
- config_file = config['docker']['compose_file']
124
- end
125
-
126
- compose = Minke::DockerCompose.new config_file
127
-
128
- begin
129
- compose.up
130
-
131
- # do we need to run any tasks after the server starts?
132
- if config['run']['after_start'] != nil
133
- config['run']['after_start'].each do |task|
134
- puts "## Running after_start task: #{task}"
135
- Rake::Task[task].invoke
136
-
137
- puts ""
138
- end
139
- end
140
-
141
- if config['run']['consul_loader']['enabled']
142
- Minke::Helpers.wait_until_server_running "#{config['run']['consul_loader']['url']}/v1/status/leader", 0
143
- loader = ConsulLoader::Loader.new(ConsulLoader::ConfigParser.new)
144
- loader.load_config config['run']['consul_loader']['config_file'], config['run']['consul_loader']['url']
145
-
146
- puts ""
147
- end
148
-
149
- compose.logs
150
- rescue SystemExit, Interrupt
151
- compose.stop
152
- compose.rm unless Docker.info["Driver"] == "btrfs"
153
- end
32
+ task :run => ['config:set_docker_env'] do
33
+ create_dependencies
34
+ runner = Minke::Tasks::Run.new @config, :run, @generator_config, @docker_runner, @docker_compose_factory, @logger, @helper
35
+ runner.run
154
36
  end
155
37
 
156
38
  desc "build and run application with Docker Compose"
157
- task :build_and_run => [:build_server, :run]
39
+ task :build_and_run => [:build_image, :run]
158
40
 
159
41
  desc "run end to end Cucumber tests USAGE: rake app:cucumber[@tag]"
160
- task :cucumber, [:feature] => ['config:set_docker_env', 'config:load_config'] do |t, args|
161
- config = Minke::Helpers.config
162
-
163
- puts "## Running cucumber with tags #{args[:feature]}"
164
-
165
- if args[:feature] != nil
166
- feature = "--tags #{args[:feature]}"
167
- else
168
- feature = ""
169
- end
42
+ task :cucumber, [:feature] => ['config:set_docker_env'] do |t, args|
43
+ create_dependencies
44
+ runner = Minke::Tasks::Cucumber.new @config, :cucumber, @generator_config, @docker_runner, @docker_compose_factory, @logger, @helper
45
+ runner.run
46
+ end
170
47
 
171
- status = 0
48
+ desc "push built image to Docker registry"
49
+ task :push do
50
+ create_dependencies
51
+ runner = Minke::Tasks::Push.new
52
+ runner.run
53
+ end
172
54
 
173
- config = Minke::Helpers.config
55
+ def create_dependencies
56
+ @system_runner = Minke::Docker::SystemRunner.new
57
+ @docker_compose_factory ||= Minke::Docker::DockerComposeFactory.new @system_runner
174
58
 
175
- if config['cucumber']['docker'] != nil && config['cucumber']['docker']['compose_file'] != nil
176
- config_file = config['cucumber']['docker']['compose_file']
177
- else
178
- config_file = config['docker']['compose_file']
59
+ if @config == nil
60
+ reader = Minke::Config::Reader.new
61
+ @config = reader.read './config.yml'
179
62
  end
180
63
 
181
- compose = Minke::DockerCompose.new config_file
182
-
183
- begin
184
- compose.up
185
-
186
- # do we need to run any tasks after the server starts?
187
- if config['cucumber']['after_start'] != nil
188
- config['cucumber']['after_start'].each do |task|
189
- puts "## Running after_start task: #{task}"
190
-
191
- begin
192
- Rake::Task[task].invoke
193
- rescue Exception => msg
194
- puts "Error running rake task: #{msg}"
195
- raise msg
196
- end
197
- puts ""
198
- end
199
- end
200
-
201
- if config['cucumber']['consul_loader']['enabled']
202
- Minke::Helpers.wait_until_server_running "#{config['cucumber']['consul_loader']['url']}/v1/status/leader", 0
203
- loader = ConsulLoader::Loader.new(ConsulLoader::ConfigParser.new)
204
- loader.load_config config['cucumber']['consul_loader']['config_file'], config['cucumber']['consul_loader']['url']
64
+ if @generator_config == nil
65
+ variables = Minke::Generators::ConfigVariables.new.tap do |v|
66
+ v.application_name = @config.application_name
67
+ v.namespace = @config.namespace
68
+ v.src_root = File.expand_path('../', __FILE__)
205
69
  end
206
70
 
207
- if config['cucumber']['health_check']['enabled']
208
- Minke::Helpers.wait_until_server_running config['cucumber']['health_check']['url'], 0, 3
209
- end
210
-
211
- sh "cucumber --color -f pretty #{feature}"
212
- status = $?.exitstatus
213
- ensure
214
- compose.stop
215
- compose.rm unless Docker.info["Driver"] == "btrfs"
216
-
217
- abort "Cucumber steps failed" unless status == 0
218
- end
219
- end
220
-
221
- desc "push built image to Docker registry"
222
- task :push => ['config:load_config'] do
223
- puts "## Push image to registry"
71
+ processor = Minke::Generators::Processor.new variables
72
+ processor.load_generators
73
+ @generator_config = processor.get_generator @config.generator_name
74
+ end
224
75
 
225
- config = Minke::Helpers.config
226
- Minke::GoDocker.tag_and_push config
76
+ @docker_runner ||= Minke::Docker::DockerRunner.new
77
+ @logger ||= Logger.new(STDOUT)
78
+ @helper ||= Minke::Helpers::Helper.new
227
79
  end
228
80
  end
@@ -1,10 +1,6 @@
1
1
  namespace :config do
2
- task :load_config do
3
- Minke::Helpers.load_config './config.yml'
4
- end
5
-
6
2
  task :set_docker_env do
7
- DOCKER_IP = Minke::Docker.get_docker_ip_address
3
+ DOCKER_IP = Minke::Docker::DockerRunner.new.get_docker_ip_address
8
4
  ENV['DOCKER_IP'] = DOCKER_IP
9
5
  end
10
6
  end
@@ -1,20 +1,22 @@
1
1
  namespace :docker do
2
2
  desc "updates build images for swagger and golang will overwrite existing images"
3
3
  task :update_images do
4
- config = Minke::Helpers.config
4
+ config = Minke::Config::Reader.new.read './config.yml'
5
5
 
6
6
  puts "## Updating Docker images"
7
- Minke::Docker.pull_image config[:build_config][:docker][:image]
7
+ runner = Minke::Docker::DockerRunner.new
8
+ runner.pull_image config.docker.build_image
8
9
 
9
10
  puts ""
10
11
  end
11
12
 
12
13
  desc "pull images for golang from Docker registry if not already downloaded"
13
14
  task :fetch_images do
14
- config = Minke::Helpers.config
15
-
15
+ config = Minke::Config::Reader.new.read './config.yml'
16
+
16
17
  puts "## Pulling Docker images"
17
- Minke::Docker.pull_image config[:build_config][:docker][:image] unless Minke::Docker.find_image config[:build_config][:docker][:image]
18
+ runner = Minke::Docker::DockerRunner.new
19
+ runner.pull_image config.docker.build_image unless runner.find_image config.docker.build_image
18
20
 
19
21
  puts ""
20
22
  end
@@ -0,0 +1,17 @@
1
+ module Minke
2
+ module Tasks
3
+ class Build < Task
4
+
5
+ def run args = nil
6
+ puts "## Build application"
7
+ run_with_block do
8
+ @generator_settings.build_settings.build_commands.build.each do |command|
9
+ puts command
10
+ run_command_in_container command
11
+ end
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ module Minke
2
+ module Tasks
3
+ class BuildImage < Task
4
+
5
+ def run args = nil
6
+ puts "## Build image"
7
+
8
+ @docker_runner.build_image @config.docker.application_docker_file, @config.application_name
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,34 @@
1
+ module Minke
2
+ module Tasks
3
+ class Cucumber < Task
4
+
5
+ def run args = nil
6
+ puts "## Running cucumber with tags #{args}"
7
+
8
+ begin
9
+ status = 0
10
+ @compose.up
11
+
12
+ run_with_block do
13
+ status = @helper.execute_shell_command "cucumber --color -f pretty #{get_features args}"
14
+ end
15
+
16
+ ensure
17
+ @compose.stop
18
+ @compose.rm
19
+
20
+ @helper.fatal_error "Cucumber steps failed" unless status == 0
21
+ end
22
+ end
23
+
24
+ def get_features args
25
+ if args != nil && args[:feature] != nil
26
+ feature = "--tags #{args[:feature]}"
27
+ else
28
+ feature = ""
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,16 @@
1
+ module Minke
2
+ module Tasks
3
+ class Fetch < Task
4
+
5
+ def run args = nil
6
+ puts "## Update dependencies"
7
+ run_with_block do
8
+ @generator_settings.build_settings.build_commands.fetch.each do |command|
9
+ run_command_in_container command
10
+ end
11
+ end
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ module Minke
2
+ module Tasks
3
+ class Push < Task
4
+
5
+ def run args = nil
6
+ puts "## Push image to registry"
7
+
8
+ url = @config.docker_registry.url
9
+ user = @config.docker_registry.user
10
+ password = @config.docker_registry.password
11
+ email = @config.docker_registry.email
12
+ namespace = @config.docker_registry.namespace
13
+ image_tag = "#{namespace}/#{@config.application_name}"
14
+
15
+ @docker_runner.login_registry url, user, password, email
16
+ @docker_runner.tag_image @config.application_name, image_tag
17
+ @docker_runner.push_image image_tag
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ module Minke
2
+ module Tasks
3
+ class Run < Task
4
+
5
+ def run args = nil
6
+ puts "## Run application with docker compose"
7
+
8
+ begin
9
+ @compose.up
10
+
11
+ run_with_block do
12
+ @compose.logs
13
+ end
14
+
15
+ ensure
16
+ @compose.stop
17
+ @compose.rm
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,107 @@
1
+ module Minke
2
+ module Tasks
3
+ ##
4
+ # Task is a base implementation of a rake task such as fetch, build, etc
5
+ class Task
6
+
7
+ def initialize config, task, generator_settings, docker_runner, docker_compose_factory, logger, helper
8
+ @config = config
9
+ @task = task
10
+ @generator_settings = generator_settings
11
+ @docker_runner = docker_runner
12
+ @logger = logger
13
+ @helper = helper
14
+ @task_settings = config.send(task)
15
+
16
+ @build_image = @generator_settings.build_settings.docker_settings.image
17
+ @build_image = config.build_image_for(task) unless config.build_image_for(task) == nil
18
+
19
+ @build_file = config.build_docker_file_for(task)
20
+
21
+ @compose_file = config.compose_file_for(task)
22
+
23
+ @compose = docker_compose_factory.create @compose_file unless @compose_file == nil
24
+ end
25
+
26
+ ##
27
+ # run_with_config executes the task steps for the given
28
+ # - block containing custom actions
29
+ def run_with_block
30
+ #TODO: Need to add some tests for this stuff
31
+ run_steps @task_settings.pre unless @task_settings == nil || @task_settings.pre == nil
32
+
33
+ yield if block_given?
34
+
35
+ run_steps @task_settings.post unless @task_settings == nil || @task_settings.post == nil
36
+ end
37
+
38
+ ##
39
+ # execute the defined steps in the given Minke::Config::TaskRunSettings
40
+ def run_steps steps
41
+ execute_rake_tasks steps.tasks unless steps.tasks == nil
42
+ load_consul_data steps.consul_loader unless steps.consul_loader == nil
43
+ wait_for_health_check steps.health_check unless steps.health_check == nil
44
+ copy_assets steps.copy unless steps.copy == nil
45
+ end
46
+
47
+ ##
48
+ # execute an array of rake tasks
49
+ def execute_rake_tasks tasks
50
+ tasks.each { |t| @helper.invoke_task t }
51
+ end
52
+
53
+ ##
54
+ # load consul config
55
+ def load_consul_data config
56
+ @helper.load_consul_data build_address(config.url), config.config_file
57
+ end
58
+
59
+ def wait_for_health_check url
60
+ @helper.wait_for_HTTPOK build_address(url), 3, 0
61
+ end
62
+
63
+ def copy_assets assets
64
+ assets.each { |a| @helper.copy_assets a.from, a.to }
65
+ end
66
+
67
+ def run_command_in_container command
68
+ begin
69
+ settings = @generator_settings.build_settings.docker_settings
70
+ if @build_file != nil
71
+ @build_image = "#{@config.application_name}-buildimage"
72
+ @docker_runner.build_image @build_file, @build_image
73
+ end
74
+
75
+ container, success = @docker_runner.create_and_run_container @build_image, settings.binds, settings.env, settings.working_directory, command
76
+
77
+ # throw exception if failed
78
+ @helper.fatal_error "Unable to run command #{command}" unless success
79
+ ensure
80
+ @docker_runner.delete_container container
81
+ end
82
+ end
83
+
84
+ def build_address url
85
+ if url.type == 'public'
86
+ "#{url.protocol}://#{url.address}:#{url.port}#{url.path}"
87
+ else
88
+ public_address = @compose.public_address url.address, url.port
89
+ "#{url.protocol}://#{public_address}#{url.path}"
90
+ end
91
+ end
92
+
93
+ def log message, level
94
+ ## implement logger implementation
95
+ case level
96
+ when :error
97
+ @logger.error message
98
+ when :info
99
+ @logger.info message
100
+ when :debug
101
+ @logger.debug message
102
+ end
103
+ end
104
+
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,17 @@
1
+ module Minke
2
+ module Tasks
3
+ class Test < Task
4
+
5
+ def run args = nil
6
+ puts "## Test application"
7
+
8
+ run_with_block do
9
+ @generator_settings.build_settings.build_commands.test.each do |command|
10
+ run_command_in_container command
11
+ end
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+ end
data/lib/minke/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Minke
2
- VERSION = "0.16.0"
2
+ VERSION = "1.0.0"
3
3
  end