devkitkat 0.1.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 +7 -0
- data/.gitignore +13 -0
- data/.gitlab-ci.yml +15 -0
- data/.rspec +3 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +74 -0
- data/LICENSE.txt +21 -0
- data/README.md +250 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/devkitkat +6 -0
- data/bin/fast_rspec +3 -0
- data/bin/setup +8 -0
- data/devkitkat.gemspec +37 -0
- data/docs/READ.md +1 -0
- data/docs/config/READ.md +1 -0
- data/docs/machine/READ.md +1 -0
- data/docs/service/READ.md +1 -0
- data/lib/devkitkat.rb +14 -0
- data/lib/devkitkat/command.rb +65 -0
- data/lib/devkitkat/config.rb +87 -0
- data/lib/devkitkat/executor.rb +63 -0
- data/lib/devkitkat/executor/docker.rb +97 -0
- data/lib/devkitkat/executor/local.rb +25 -0
- data/lib/devkitkat/main.rb +46 -0
- data/lib/devkitkat/service.rb +243 -0
- data/lib/devkitkat/version.rb +3 -0
- metadata +225 -0
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "devkitkat"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
require "pry"
|
11
|
+
Pry.start
|
12
|
+
|
13
|
+
# require "irb"
|
14
|
+
# IRB.start(__FILE__)
|
data/bin/devkitkat
ADDED
data/bin/fast_rspec
ADDED
data/bin/setup
ADDED
data/devkitkat.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "devkitkat/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "devkitkat"
|
8
|
+
spec.version = Devkitkat::VERSION
|
9
|
+
spec.authors = ["Shinya Maeda"]
|
10
|
+
spec.email = ["shinya@gitlab.com"]
|
11
|
+
|
12
|
+
spec.summary = "Make micro services easy"
|
13
|
+
spec.description = "Make micro services easy"
|
14
|
+
spec.homepage = "https://gitlab.com/dosuken123/devkitkat"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Specify which files should be added to the gem when it is released.
|
18
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
19
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
20
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
21
|
+
end
|
22
|
+
spec.bindir = "bin"
|
23
|
+
spec.executables = "devkitkat"
|
24
|
+
spec.require_paths = ["lib"]
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.17"
|
27
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
29
|
+
spec.add_development_dependency "rspec-temp_dir", "~> 1.1.0"
|
30
|
+
spec.add_development_dependency "pry", "~> 0.12.2"
|
31
|
+
spec.add_development_dependency "pry-nav"
|
32
|
+
spec.add_runtime_dependency "activesupport", "~> 6.0.0"
|
33
|
+
spec.add_runtime_dependency "parallel", "~> 1.17.0"
|
34
|
+
spec.add_runtime_dependency "ruby-progressbar", "~> 1.10.1"
|
35
|
+
spec.add_runtime_dependency "colorize", "~> 0.8.1"
|
36
|
+
spec.add_runtime_dependency "docker-api", "~> 1.34.2"
|
37
|
+
end
|
data/docs/READ.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Devkitkat
|
data/docs/config/READ.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Config
|
@@ -0,0 +1 @@
|
|
1
|
+
# Machine
|
@@ -0,0 +1 @@
|
|
1
|
+
# Service
|
data/lib/devkitkat.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "devkitkat/version"
|
2
|
+
require "devkitkat/main"
|
3
|
+
require "devkitkat/executor"
|
4
|
+
require "devkitkat/command"
|
5
|
+
require "devkitkat/config"
|
6
|
+
require "devkitkat/service"
|
7
|
+
require 'yaml'
|
8
|
+
require 'optparse'
|
9
|
+
require 'parallel'
|
10
|
+
require 'colorize'
|
11
|
+
require 'active_support/core_ext/array/conversions'
|
12
|
+
|
13
|
+
module Devkitkat
|
14
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Devkitkat
|
2
|
+
class Command
|
3
|
+
attr_reader :options, :script, :target, :args
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@options = {}
|
7
|
+
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.banner = "Usage: devkitkat <script> <target> [options]"
|
10
|
+
|
11
|
+
opts.on("-p", "--path PATH", "The root path of the .devkitkat.yml") do |v|
|
12
|
+
options[:root_path] = v
|
13
|
+
end
|
14
|
+
|
15
|
+
opts.on("-e", "--exclude SERVICE", "Exclude serviced from the specified target") do |v|
|
16
|
+
options[:exclude] ||= []
|
17
|
+
options[:exclude] << v
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on("-e", "--env-var VARIABLE", "additional environment variables") do |v|
|
21
|
+
options[:variables] ||= {}
|
22
|
+
options[:variables].merge!(Hash[*v.split('=')])
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on("-d", "--depth DEPTH", "Git depth for pull/fetch") do |v|
|
26
|
+
options[:git_depth] = v
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on("-r", "--remote REMOTE", "Git remote") do |v|
|
30
|
+
options[:git_remote] = v
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on("-b", "--branch BRANCH", "Git branch") do |v|
|
34
|
+
options[:git_branch] = v
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on("-t", "--tty", "TTY mode. In this mode, log won't be emitted.") do |v|
|
38
|
+
options[:tty] = v
|
39
|
+
end
|
40
|
+
end.parse!
|
41
|
+
|
42
|
+
@script, @target, *@args = ARGV
|
43
|
+
end
|
44
|
+
|
45
|
+
def tty?
|
46
|
+
options[:tty]
|
47
|
+
end
|
48
|
+
|
49
|
+
def variables
|
50
|
+
options[:variables]
|
51
|
+
end
|
52
|
+
|
53
|
+
def tmp_dir
|
54
|
+
File.join(kit_root, 'tmp')
|
55
|
+
end
|
56
|
+
|
57
|
+
def create_tmp_dir
|
58
|
+
FileUtils.mkdir_p(tmp_dir)
|
59
|
+
end
|
60
|
+
|
61
|
+
def kit_root
|
62
|
+
Dir.pwd # TODO: root_path
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Devkitkat
|
2
|
+
class Config
|
3
|
+
DEVKITKAT_FILE_NAME = '.devkitkat.yml'
|
4
|
+
HIDDEN_SERVICES = %w[system]
|
5
|
+
|
6
|
+
attr_reader :devkitkat_yml, :kit_root
|
7
|
+
|
8
|
+
def initialize(kit_root)
|
9
|
+
@kit_root = kit_root
|
10
|
+
@devkitkat_yml = load_config
|
11
|
+
end
|
12
|
+
|
13
|
+
def all_services
|
14
|
+
services + HIDDEN_SERVICES
|
15
|
+
end
|
16
|
+
|
17
|
+
def resolve!(target, exclude: nil)
|
18
|
+
services = if target.nil? || target == 'system'
|
19
|
+
%w[system]
|
20
|
+
elsif target == 'all'
|
21
|
+
all_services
|
22
|
+
elsif group = find_group(target)
|
23
|
+
services_for_group(group)
|
24
|
+
elsif service = find_service(target)
|
25
|
+
[service]
|
26
|
+
else
|
27
|
+
raise ArgumentError, "The target name #{target} couldn't be resolved"
|
28
|
+
end
|
29
|
+
|
30
|
+
services = services - exclude if exclude
|
31
|
+
|
32
|
+
services
|
33
|
+
end
|
34
|
+
|
35
|
+
def environment_type
|
36
|
+
devkitkat_yml.dig('environment', 'type') || 'local'
|
37
|
+
end
|
38
|
+
|
39
|
+
def environment_image
|
40
|
+
devkitkat_yml.dig('environment', 'image')
|
41
|
+
end
|
42
|
+
|
43
|
+
def application
|
44
|
+
devkitkat_yml.fetch('application', '')
|
45
|
+
end
|
46
|
+
|
47
|
+
def variables
|
48
|
+
devkitkat_yml.fetch('variables', {})
|
49
|
+
end
|
50
|
+
|
51
|
+
def service_hash(name)
|
52
|
+
devkitkat_yml.dig('services', name) || {}
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def services
|
58
|
+
devkitkat_yml['services']&.keys || []
|
59
|
+
end
|
60
|
+
|
61
|
+
def groups
|
62
|
+
devkitkat_yml['groups']&.keys || []
|
63
|
+
end
|
64
|
+
|
65
|
+
def services_for_group(group)
|
66
|
+
devkitkat_yml.dig('groups', group) || []
|
67
|
+
end
|
68
|
+
|
69
|
+
def find_group(target)
|
70
|
+
groups.find { |group| group == target }
|
71
|
+
end
|
72
|
+
|
73
|
+
def find_service(target)
|
74
|
+
services.find { |service| service == target }
|
75
|
+
end
|
76
|
+
|
77
|
+
def load_config
|
78
|
+
File.read(config_path).yield_self do |content|
|
79
|
+
YAML.load(content)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def config_path
|
84
|
+
File.join(kit_root, DEVKITKAT_FILE_NAME)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "devkitkat/executor/docker"
|
2
|
+
require "devkitkat/executor/local"
|
3
|
+
|
4
|
+
module Devkitkat
|
5
|
+
class Executor
|
6
|
+
attr_reader :service, :scripts
|
7
|
+
|
8
|
+
delegate :config, :command, to: :service
|
9
|
+
delegate :prepare, :cleanup, to: :executor
|
10
|
+
|
11
|
+
SCRIPT_HEADER = <<-EOS
|
12
|
+
#!/bin/bash
|
13
|
+
set -e
|
14
|
+
EOS
|
15
|
+
|
16
|
+
def initialize(service)
|
17
|
+
@service = service
|
18
|
+
delete_script_file
|
19
|
+
end
|
20
|
+
|
21
|
+
def write(cmd)
|
22
|
+
ensure_script_file
|
23
|
+
|
24
|
+
File.open(script_file, 'a') do |stream|
|
25
|
+
stream.write(cmd + "\n")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def commit
|
30
|
+
executor.commit(script_file)
|
31
|
+
ensure
|
32
|
+
delete_script_file
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def executor
|
38
|
+
@executor ||= klass.new(service)
|
39
|
+
end
|
40
|
+
|
41
|
+
def klass
|
42
|
+
Object.const_get("Devkitkat::Executor::#{config.environment_type.capitalize}")
|
43
|
+
end
|
44
|
+
|
45
|
+
def script_file
|
46
|
+
File.join(command.tmp_dir, "script-#{service.name}-#{command.script}")
|
47
|
+
end
|
48
|
+
|
49
|
+
def ensure_script_file
|
50
|
+
create_script_file unless File.exist?(script_file)
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_script_file
|
54
|
+
command.create_tmp_dir
|
55
|
+
File.write(script_file, SCRIPT_HEADER)
|
56
|
+
File.chmod(0777, script_file)
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete_script_file
|
60
|
+
FileUtils.rm_f(script_file)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
2
|
+
require 'docker'
|
3
|
+
|
4
|
+
module Devkitkat
|
5
|
+
class Executor
|
6
|
+
class Docker
|
7
|
+
attr_reader :service, :script_file
|
8
|
+
|
9
|
+
delegate :config, :command, to: :service
|
10
|
+
|
11
|
+
def initialize(service)
|
12
|
+
@service = service
|
13
|
+
end
|
14
|
+
|
15
|
+
def prepare
|
16
|
+
start_container
|
17
|
+
end
|
18
|
+
|
19
|
+
def cleanup
|
20
|
+
stop_container
|
21
|
+
end
|
22
|
+
|
23
|
+
def commit(script_file)
|
24
|
+
@script_file = script_file
|
25
|
+
|
26
|
+
rewrite_root_path!
|
27
|
+
new_path = script_path_in_container
|
28
|
+
|
29
|
+
container.exec([new_path])
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def rewrite_root_path!
|
35
|
+
content = File.read(script_file)
|
36
|
+
new_content = content.gsub(command.kit_root, root_in_container)
|
37
|
+
File.write(script_file, new_content)
|
38
|
+
end
|
39
|
+
|
40
|
+
def script_path_in_container
|
41
|
+
relative_path = script_file.delete_prefix(command.kit_root)
|
42
|
+
File.join(root_in_container, relative_path)
|
43
|
+
end
|
44
|
+
|
45
|
+
def log_path_in_container
|
46
|
+
relative_path = service.log_path.delete_prefix(command.kit_root)
|
47
|
+
File.join(root_in_container, relative_path)
|
48
|
+
end
|
49
|
+
|
50
|
+
def docker_image
|
51
|
+
config.environment_image
|
52
|
+
end
|
53
|
+
|
54
|
+
def container
|
55
|
+
@container ||= ::Docker::Container.create(container_parameter)
|
56
|
+
end
|
57
|
+
|
58
|
+
def container_parameter
|
59
|
+
# TODO: Speicfy users otherwise the created files are owned by root
|
60
|
+
params = {
|
61
|
+
'Cmd' => %w[tail -f],
|
62
|
+
'Image' => docker_image,
|
63
|
+
'name' => service.container_name,
|
64
|
+
'HostConfig' => {
|
65
|
+
'Binds' => ["#{command.kit_root}:#{root_in_container}"]
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
if service.port
|
70
|
+
params.deep_merge!(
|
71
|
+
'ExposedPorts' => { "#{service.port}/tcp" => {} },
|
72
|
+
'HostConfig' => {
|
73
|
+
'PortBindings' => {
|
74
|
+
"#{service.port}/tcp" => [{ 'HostPort' => service.port.to_s }]
|
75
|
+
}
|
76
|
+
}
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
params
|
81
|
+
end
|
82
|
+
|
83
|
+
def root_in_container
|
84
|
+
"/devkitkat"
|
85
|
+
end
|
86
|
+
|
87
|
+
def start_container
|
88
|
+
container.start
|
89
|
+
end
|
90
|
+
|
91
|
+
def stop_container
|
92
|
+
container.stop
|
93
|
+
container.remove
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Devkitkat
|
2
|
+
class Executor
|
3
|
+
class Local
|
4
|
+
attr_reader :service
|
5
|
+
|
6
|
+
delegate :config, :command, to: :service
|
7
|
+
|
8
|
+
def initialize(service)
|
9
|
+
@service = service
|
10
|
+
end
|
11
|
+
|
12
|
+
def prepare
|
13
|
+
# no-op
|
14
|
+
end
|
15
|
+
|
16
|
+
def cleanup
|
17
|
+
# no-op
|
18
|
+
end
|
19
|
+
|
20
|
+
def commit(script_file)
|
21
|
+
system(script_file)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|