kuber_kit 0.3.9 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +35 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +1 -1
  5. data/TODO.md +2 -3
  6. data/example/configurations/review.rb +1 -0
  7. data/example/infrastructure/artifacts.rb +1 -1
  8. data/example/services/docker_app.rb +12 -0
  9. data/lib/kuber_kit.rb +6 -4
  10. data/lib/kuber_kit/actions/configuration_loader.rb +12 -19
  11. data/lib/kuber_kit/actions/env_file_reader.rb +1 -0
  12. data/lib/kuber_kit/actions/image_compiler.rb +10 -6
  13. data/lib/kuber_kit/actions/service_deployer.rb +24 -11
  14. data/lib/kuber_kit/actions/template_reader.rb +1 -0
  15. data/lib/kuber_kit/artifacts_sync/artifacts_updater.rb +3 -2
  16. data/lib/kuber_kit/cli.rb +49 -31
  17. data/lib/kuber_kit/container.rb +5 -1
  18. data/lib/kuber_kit/core/configuration.rb +26 -24
  19. data/lib/kuber_kit/core/configuration_definition.rb +17 -10
  20. data/lib/kuber_kit/core/configuration_factory.rb +10 -9
  21. data/lib/kuber_kit/core/configuration_store.rb +2 -2
  22. data/lib/kuber_kit/core/image_store.rb +2 -2
  23. data/lib/kuber_kit/core/service_store.rb +2 -2
  24. data/lib/kuber_kit/image_compiler/compiler.rb +3 -1
  25. data/lib/kuber_kit/image_compiler/image_builder.rb +9 -1
  26. data/lib/kuber_kit/service_deployer/strategies/docker.rb +23 -5
  27. data/lib/kuber_kit/service_deployer/strategies/docker_compose.rb +4 -4
  28. data/lib/kuber_kit/service_deployer/strategies/kubernetes.rb +3 -1
  29. data/lib/kuber_kit/shell/commands/docker_commands.rb +52 -11
  30. data/lib/kuber_kit/shell/commands/docker_compose_commands.rb +1 -1
  31. data/lib/kuber_kit/shell/local_shell.rb +6 -6
  32. data/lib/kuber_kit/shell/ssh_shell.rb +4 -4
  33. data/lib/kuber_kit/tools/logger_factory.rb +1 -1
  34. data/lib/kuber_kit/ui/api.rb +48 -0
  35. data/lib/kuber_kit/ui/debug.rb +31 -0
  36. data/lib/kuber_kit/ui/interactive.rb +15 -0
  37. data/lib/kuber_kit/ui/simple.rb +34 -5
  38. data/lib/kuber_kit/version.rb +1 -1
  39. metadata +10 -6
@@ -258,8 +258,12 @@ class KuberKit::Container
258
258
  end
259
259
 
260
260
  register "ui" do
261
- if KuberKit.debug_mode?
261
+ if KuberKit.ui_mode == :debug
262
+ KuberKit::UI::Debug.new
263
+ elsif KuberKit.ui_mode == :simple
262
264
  KuberKit::UI::Simple.new
265
+ elsif KuberKit.ui_mode == :api
266
+ KuberKit::UI::Api.new
263
267
  else
264
268
  KuberKit::UI::Interactive.new
265
269
  end
@@ -1,35 +1,37 @@
1
1
  class KuberKit::Core::Configuration
2
2
  attr_reader :name, :artifacts, :registries, :env_files, :templates, :kubeconfig_path,
3
- :deployer_strategy, :deployer_namespace, :services_attributes, :build_servers,
4
- :global_build_vars
3
+ :services_attributes, :build_servers, :global_build_vars,
4
+ :deployer_strategy, :deployer_namespace, :deployer_require_confirimation
5
5
 
6
6
  Contract KeywordArgs[
7
- name: Symbol,
8
- artifacts: Hash,
9
- registries: Hash,
10
- env_files: Hash,
11
- templates: Hash,
12
- kubeconfig_path: Maybe[String],
13
- deployer_strategy: Symbol,
14
- deployer_namespace: Maybe[Symbol],
15
- services_attributes: HashOf[Symbol => Hash],
16
- build_servers: ArrayOf[KuberKit::Core::BuildServers::AbstractBuildServer],
17
- global_build_vars: HashOf[Symbol => Any],
7
+ name: Symbol,
8
+ artifacts: Hash,
9
+ registries: Hash,
10
+ env_files: Hash,
11
+ templates: Hash,
12
+ kubeconfig_path: Maybe[String],
13
+ services_attributes: HashOf[Symbol => Hash],
14
+ build_servers: ArrayOf[KuberKit::Core::BuildServers::AbstractBuildServer],
15
+ global_build_vars: HashOf[Symbol => Any],
16
+ deployer_strategy: Symbol,
17
+ deployer_namespace: Maybe[Symbol],
18
+ deployer_require_confirimation: Bool,
18
19
  ] => Any
19
20
  def initialize(name:, artifacts:, registries:, env_files:, templates:, kubeconfig_path:,
20
- deployer_strategy:, deployer_namespace:, services_attributes:, build_servers:,
21
- global_build_vars:)
22
- @name = name
23
- @artifacts = artifacts
24
- @registries = registries
25
- @env_files = env_files
26
- @templates = templates
27
- @kubeconfig_path = kubeconfig_path
28
- @deployer_strategy = deployer_strategy
29
- @deployer_namespace = deployer_namespace
30
- @build_servers = build_servers
21
+ services_attributes:, build_servers:, global_build_vars:,
22
+ deployer_strategy:, deployer_namespace:, deployer_require_confirimation:)
23
+ @name = name
24
+ @artifacts = artifacts
25
+ @registries = registries
26
+ @env_files = env_files
27
+ @templates = templates
28
+ @kubeconfig_path = kubeconfig_path
29
+ @build_servers = build_servers
31
30
  @services_attributes = services_attributes
32
31
  @global_build_vars = global_build_vars
32
+ @deployer_strategy = deployer_strategy
33
+ @deployer_namespace = deployer_namespace
34
+ @deployer_require_confirimation = deployer_require_confirimation
33
35
  end
34
36
 
35
37
  def service_attributes(service_name)
@@ -17,18 +17,19 @@ class KuberKit::Core::ConfigurationDefinition
17
17
 
18
18
  def to_attrs
19
19
  OpenStruct.new(
20
- name: @configuration_name,
21
- artifacts: @artifacts,
22
- registries: @registries,
23
- env_files: @env_files,
24
- templates: @templates,
25
- kubeconfig_path: @kubeconfig_path,
26
- deployer_strategy: @deployer_strategy,
27
- deployer_namespace: @deployer_namespace,
28
- enabled_services: @enabled_services,
29
- build_servers: @build_servers,
20
+ name: @configuration_name,
21
+ artifacts: @artifacts,
22
+ registries: @registries,
23
+ env_files: @env_files,
24
+ templates: @templates,
25
+ kubeconfig_path: @kubeconfig_path,
26
+ enabled_services: @enabled_services,
27
+ build_servers: @build_servers,
30
28
  services_attributes: @services_attributes,
31
29
  global_build_vars: @global_build_vars,
30
+ deployer_strategy: @deployer_strategy,
31
+ deployer_namespace: @deployer_namespace,
32
+ deployer_require_confirimation: @deployer_require_confirimation || false,
32
33
  )
33
34
  end
34
35
 
@@ -94,6 +95,12 @@ class KuberKit::Core::ConfigurationDefinition
94
95
  self
95
96
  end
96
97
 
98
+ def deployer_require_confirimation
99
+ @deployer_require_confirimation = true
100
+
101
+ self
102
+ end
103
+
97
104
  def enabled_services(services)
98
105
  if services.is_a?(Hash)
99
106
  @enabled_services += services.keys.map(&:to_sym)
@@ -20,17 +20,18 @@ class KuberKit::Core::ConfigurationFactory
20
20
  build_servers = fetch_build_servers(configuration_attrs.build_servers)
21
21
 
22
22
  KuberKit::Core::Configuration.new(
23
- name: configuration_attrs.name,
24
- artifacts: artifacts,
25
- registries: registries,
26
- env_files: env_files,
27
- templates: templates,
28
- kubeconfig_path: configuration_attrs.kubeconfig_path,
29
- deployer_strategy: configuration_attrs.deployer_strategy || configs.deployer_strategy,
30
- deployer_namespace: configuration_attrs.deployer_namespace,
31
- build_servers: build_servers,
23
+ name: configuration_attrs.name,
24
+ artifacts: artifacts,
25
+ registries: registries,
26
+ env_files: env_files,
27
+ templates: templates,
28
+ kubeconfig_path: configuration_attrs.kubeconfig_path,
29
+ build_servers: build_servers,
32
30
  services_attributes: configuration_attrs.services_attributes,
33
31
  global_build_vars: configuration_attrs.global_build_vars || {},
32
+ deployer_strategy: configuration_attrs.deployer_strategy || configs.deployer_strategy,
33
+ deployer_namespace: configuration_attrs.deployer_namespace,
34
+ deployer_require_confirimation: configuration_attrs.deployer_require_confirimation,
34
35
  )
35
36
  end
36
37
 
@@ -3,7 +3,7 @@ class KuberKit::Core::ConfigurationStore
3
3
  "core.configuration_factory",
4
4
  "core.configuration_definition_factory",
5
5
  "shell.local_shell",
6
- "tools.logger"
6
+ "ui"
7
7
  ]
8
8
 
9
9
  def define(configuration_name)
@@ -33,7 +33,7 @@ class KuberKit::Core::ConfigurationStore
33
33
  load_definition(path)
34
34
  end
35
35
  rescue KuberKit::Shell::AbstractShell::DirNotFoundError
36
- logger.warn("Directory with configurations not found: #{dir_path}")
36
+ ui.print_warning("ConfigurationStore", "Directory with configurations not found: #{dir_path}")
37
37
  []
38
38
  end
39
39
 
@@ -3,7 +3,7 @@ class KuberKit::Core::ImageStore
3
3
  "core.image_factory",
4
4
  "core.image_definition_factory",
5
5
  "shell.local_shell",
6
- "tools.logger"
6
+ "ui"
7
7
  ]
8
8
 
9
9
  def define(image_name, image_dir = nil)
@@ -33,7 +33,7 @@ class KuberKit::Core::ImageStore
33
33
  load_definition(path)
34
34
  end
35
35
  rescue KuberKit::Shell::AbstractShell::DirNotFoundError
36
- logger.warn("Directory with images not found: #{dir_path}")
36
+ ui.print_warning("ImageStore", "Directory with images not found: #{dir_path}")
37
37
  []
38
38
  end
39
39
 
@@ -3,7 +3,7 @@ class KuberKit::Core::ServiceStore
3
3
  "core.service_factory",
4
4
  "core.service_definition_factory",
5
5
  "shell.local_shell",
6
- "tools.logger"
6
+ "ui",
7
7
  ]
8
8
 
9
9
  def define(service_name)
@@ -33,7 +33,7 @@ class KuberKit::Core::ServiceStore
33
33
  load_definition(path)
34
34
  end
35
35
  rescue KuberKit::Shell::AbstractShell::DirNotFoundError
36
- logger.warn("Directory with services not found: #{dir_path}")
36
+ ui.print_warning("ServiceStore", "Directory with services not found: #{dir_path}")
37
37
  []
38
38
  end
39
39
 
@@ -12,7 +12,9 @@ class KuberKit::ImageCompiler::Compiler
12
12
  context_helper = context_helper_factory.build_image_context(shell, image)
13
13
  image_build_dir_creator.create(shell, image, image_build_dir, context_helper: context_helper)
14
14
 
15
- image_builder.build(shell, image, image_build_dir, context_helper: context_helper)
15
+ result = image_builder.build(shell, image, image_build_dir, context_helper: context_helper)
16
16
  image_build_dir_creator.cleanup(shell, image_build_dir)
17
+
18
+ result
17
19
  end
18
20
  end
@@ -10,7 +10,13 @@ class KuberKit::ImageCompiler::ImageBuilder
10
10
  def build(shell, image, build_dir, context_helper: nil)
11
11
  image.before_build_callback.call(context_helper, build_dir) if image.before_build_callback
12
12
 
13
- docker_commands.build(shell, build_dir, ["-t=#{image.registry_url}"])
13
+ build_options = ["-t=#{image.registry_url}"]
14
+ # use quite option for api mode ui, so it will only return built image id
15
+ if KuberKit.ui_mode == :api
16
+ build_options << "-q"
17
+ end
18
+
19
+ build_result = docker_commands.build(shell, build_dir, build_options)
14
20
 
15
21
  version_tag = version_tag_builder.get_version
16
22
  docker_commands.tag(shell, image.registry_url, version_tag)
@@ -21,5 +27,7 @@ class KuberKit::ImageCompiler::ImageBuilder
21
27
  end
22
28
 
23
29
  image.after_build_callback.call(context_helper, build_dir) if image.after_build_callback
30
+
31
+ build_result
24
32
  end
25
33
  end
@@ -10,8 +10,10 @@ class KuberKit::ServiceDeployer::Strategies::Docker < KuberKit::ServiceDeployer:
10
10
  :image_name,
11
11
  :detached,
12
12
  :command_name,
13
- :command_args,
14
- :delete_if_exists
13
+ :custom_args,
14
+ :delete_if_exists,
15
+ :volumes,
16
+ :networks,
15
17
  ]
16
18
 
17
19
  Contract KuberKit::Shell::AbstractShell, KuberKit::Core::Service => Any
@@ -23,8 +25,10 @@ class KuberKit::ServiceDeployer::Strategies::Docker < KuberKit::ServiceDeployer:
23
25
  end
24
26
 
25
27
  container_name = strategy_options.fetch(:container_name, service.uri)
26
- command_name = strategy_options.fetch(:command_name, "bash")
27
- command_args = strategy_options.fetch(:command_args, nil)
28
+ command_name = strategy_options.fetch(:command_name, nil)
29
+ custom_args = strategy_options.fetch(:custom_args, nil)
30
+ networks = strategy_options.fetch(:networks, [])
31
+ volumes = strategy_options.fetch(:volumes, [])
28
32
 
29
33
  image_name = strategy_options.fetch(:image_name, nil)
30
34
  if image_name.nil?
@@ -37,10 +41,24 @@ class KuberKit::ServiceDeployer::Strategies::Docker < KuberKit::ServiceDeployer:
37
41
  docker_commands.delete_container(shell, container_name)
38
42
  end
39
43
 
44
+ custom_args = Array(custom_args)
45
+ if container_name
46
+ custom_args << "--name #{container_name}"
47
+ end
48
+ networks.each do |network|
49
+ docker_commands.create_network(shell, network)
50
+ custom_args << "--network #{network}"
51
+ end
52
+ volumes.each do |volume|
53
+ volume_name, _ = volume.split(":")
54
+ docker_commands.create_volume(shell, volume_name) unless volume_name.start_with?("/")
55
+ custom_args << "--volume #{volume}"
56
+ end
57
+
40
58
  docker_commands.run(
41
59
  shell, image.remote_registry_url,
42
60
  command: command_name,
43
- args: command_args,
61
+ args: custom_args,
44
62
  detached: !!strategy_options[:detached]
45
63
  )
46
64
  end
@@ -8,7 +8,7 @@ class KuberKit::ServiceDeployer::Strategies::DockerCompose < KuberKit::ServiceDe
8
8
  STRATEGY_OPTIONS = [
9
9
  :service_name,
10
10
  :command_name,
11
- :command_args,
11
+ :custom_args,
12
12
  :detached
13
13
  ]
14
14
 
@@ -25,13 +25,13 @@ class KuberKit::ServiceDeployer::Strategies::DockerCompose < KuberKit::ServiceDe
25
25
  end
26
26
 
27
27
  service_name = strategy_options.fetch(:service_name, service.name.to_s)
28
- command_name = strategy_options.fetch(:command_name, "bash")
29
- command_args = strategy_options.fetch(:command_args, nil)
28
+ command_name = strategy_options.fetch(:command_name, nil)
29
+ custom_args = strategy_options.fetch(:custom_args, nil)
30
30
 
31
31
  docker_compose_commands.run(shell, config_path,
32
32
  service: service_name,
33
33
  command: command_name,
34
- args: command_args,
34
+ args: custom_args,
35
35
  detached: !!strategy_options[:detached]
36
36
  )
37
37
  end
@@ -39,7 +39,7 @@ class KuberKit::ServiceDeployer::Strategies::Kubernetes < KuberKit::ServiceDeplo
39
39
  kubectl_commands.delete_resource(shell, resource_type, resource_name, kubeconfig_path: kubeconfig_path, namespace: namespace)
40
40
  end
41
41
 
42
- kubectl_commands.apply_file(shell, config_path, kubeconfig_path: kubeconfig_path, namespace: namespace)
42
+ apply_result = kubectl_commands.apply_file(shell, config_path, kubeconfig_path: kubeconfig_path, namespace: namespace)
43
43
 
44
44
  restart_enabled = strategy_options.fetch(:restart_if_exists, true)
45
45
  if restart_enabled && resource_exists
@@ -48,5 +48,7 @@ class KuberKit::ServiceDeployer::Strategies::Kubernetes < KuberKit::ServiceDeplo
48
48
  kubeconfig_path: kubeconfig_path, namespace: namespace
49
49
  )
50
50
  end
51
+
52
+ apply_result
51
53
  end
52
54
  end
@@ -3,7 +3,7 @@ class KuberKit::Shell::Commands::DockerCommands
3
3
  default_args = ["--rm=true"]
4
4
  args_list = (default_args + args).join(" ")
5
5
 
6
- shell.exec!(%Q{docker build #{build_dir} #{args_list}})
6
+ shell.exec!(%Q{docker image build #{build_dir} #{args_list}})
7
7
  end
8
8
 
9
9
  def tag(shell, image_name, tag_name)
@@ -18,7 +18,7 @@ class KuberKit::Shell::Commands::DockerCommands
18
18
  command_parts = []
19
19
  command_parts << "docker run"
20
20
  command_parts << "-d" if detached
21
- command_parts << args if args
21
+ command_parts << Array(args).join(" ") if args
22
22
  command_parts << image_name
23
23
  command_parts << command if command
24
24
 
@@ -29,26 +29,67 @@ class KuberKit::Shell::Commands::DockerCommands
29
29
  end
30
30
  end
31
31
 
32
- def container_exists?(shell, container_name)
33
- result = get_container_id(shell, container_name)
32
+ def container_exists?(shell, container_name, status: nil)
33
+ result = get_containers(shell, container_name, status: status)
34
34
  result && result != ""
35
35
  end
36
36
 
37
- def delete_container(shell, container_name)
38
- shell.exec!(%Q{docker rm -f #{container_name}})
39
- end
40
-
41
- def get_container_id(shell, container_name, only_healthy: false, status: "running")
37
+ def get_containers(shell, container_name, only_healthy: false, status: nil)
42
38
  command_parts = []
43
39
  command_parts << "docker ps -a -q"
44
40
 
45
41
  if only_healthy
46
42
  command_parts << "--filter=\"health=healthy\""
47
43
  end
48
-
49
- command_parts << "--filter=\"status=#{status}\""
44
+ if status
45
+ command_parts << "--filter=\"status=#{status}\""
46
+ end
50
47
  command_parts << "--filter=\"name=#{container_name}\""
51
48
 
52
49
  shell.exec!(command_parts.join(" "))
53
50
  end
51
+
52
+ def delete_container(shell, container_name)
53
+ shell.exec!("docker rm -f #{container_name}")
54
+ end
55
+
56
+ def create_network(shell, name)
57
+ unless network_exists?(shell, name)
58
+ shell.exec!("docker network create #{name}")
59
+ end
60
+ end
61
+
62
+ def network_exists?(shell, network_name)
63
+ result = get_networks(shell, network_name)
64
+ result && result != ""
65
+ end
66
+
67
+ def get_networks(shell, network_name)
68
+ command_parts = []
69
+ command_parts << "docker network ls"
70
+ command_parts << "--filter=\"name=#{network_name}\""
71
+ command_parts << "--format \"{{.Name}}\""
72
+
73
+ shell.exec!(command_parts.join(" "))
74
+ end
75
+
76
+ def create_volume(shell, name)
77
+ unless volume_exists?(shell, name)
78
+ shell.exec!("docker volume create #{name}")
79
+ end
80
+ end
81
+
82
+ def volume_exists?(shell, volume_name)
83
+ result = get_volumes(shell, volume_name)
84
+ result && result != ""
85
+ end
86
+
87
+ def get_volumes(shell, volume_name)
88
+ command_parts = []
89
+ command_parts << "docker volume ls"
90
+ command_parts << "--filter=\"name=#{volume_name}\""
91
+ command_parts << "--format \"{{.Name}}\""
92
+
93
+ shell.exec!(command_parts.join(" "))
94
+ end
54
95
  end
@@ -8,7 +8,7 @@ class KuberKit::Shell::Commands::DockerComposeCommands
8
8
 
9
9
 
10
10
  command_parts << "-d" if detached
11
- command_parts << args if args
11
+ command_parts << Array(args).join(" ") if args
12
12
  command_parts << service
13
13
  command_parts << command if command
14
14
 
@@ -2,16 +2,16 @@ require 'fileutils'
2
2
 
3
3
  class KuberKit::Shell::LocalShell < KuberKit::Shell::AbstractShell
4
4
  include KuberKit::Import[
5
- "tools.logger",
6
5
  "shell.command_counter",
7
6
  "shell.rsync_commands",
7
+ "ui",
8
8
  ]
9
9
 
10
10
  def exec!(command, log_command: true)
11
11
  command_number = command_counter.get_number.to_s.rjust(2, "0")
12
12
 
13
13
  if log_command
14
- logger.info("Execute: [#{command_number}]: #{command.to_s.cyan}")
14
+ ui.print_debug("LocalShell", "Execute: [#{command_number}]: #{command.to_s.cyan}")
15
15
  end
16
16
 
17
17
  result = nil
@@ -20,7 +20,7 @@ class KuberKit::Shell::LocalShell < KuberKit::Shell::AbstractShell
20
20
  end
21
21
 
22
22
  if result && result != "" && log_command
23
- logger.info("Finished [#{command_number}] with result: \n#{result.grey}")
23
+ ui.print_debug("LocalShell", "Finished [#{command_number}] with result: \n ----\n#{result.grey}\n ----")
24
24
  end
25
25
 
26
26
  if $?.exitstatus != 0
@@ -34,7 +34,7 @@ class KuberKit::Shell::LocalShell < KuberKit::Shell::AbstractShell
34
34
  command_number = command_counter.get_number.to_s.rjust(2, "0")
35
35
 
36
36
  if log_command
37
- logger.info("Interactive: [#{command_number}]: #{command.to_s.cyan}")
37
+ ui.print_debug("LocalShell", "Interactive: [#{command_number}]: #{command.to_s.cyan}")
38
38
  end
39
39
 
40
40
  result = system(command)
@@ -57,7 +57,7 @@ class KuberKit::Shell::LocalShell < KuberKit::Shell::AbstractShell
57
57
 
58
58
  File.write(file_path, content)
59
59
 
60
- logger.info("Created file #{file_path.to_s.cyan}\r\n#{content.grey}")
60
+ ui.print_debug("LocalShell", "Created file #{file_path.to_s.cyan}\r\n ----\r\n#{content.grey}\r\n ----")
61
61
 
62
62
  true
63
63
  end
@@ -76,7 +76,7 @@ class KuberKit::Shell::LocalShell < KuberKit::Shell::AbstractShell
76
76
 
77
77
  def recursive_list_files(path, name: nil)
78
78
  command = %Q{find -L #{path} -type f}
79
- command += " -name #{name}" if name
79
+ command += " -name '#{name}'" if name
80
80
  exec!(command).split(/[\r\n]+/)
81
81
  rescue => e
82
82
  if e.message.include?("No such file or directory")