minke 0.16.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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