kuber_kit 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.
Files changed (118) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +3 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +7 -0
  7. data/Gemfile +8 -0
  8. data/Gemfile.lock +67 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +19 -0
  11. data/Rakefile +6 -0
  12. data/TODO.md +2 -0
  13. data/bin/console +14 -0
  14. data/bin/kit +8 -0
  15. data/example/app_data/service.yml +7 -0
  16. data/example/app_data/test.env +2 -0
  17. data/example/app_data/test.txt +1 -0
  18. data/example/configurations/review.rb +4 -0
  19. data/example/images/app_sources/Dockerfile +6 -0
  20. data/example/images/app_sources/build_context/source.rb +2 -0
  21. data/example/images/app_sources/image.rb +4 -0
  22. data/example/images/ruby/Dockerfile +1 -0
  23. data/example/images/ruby/image.rb +3 -0
  24. data/example/images/ruby_app/Dockerfile +11 -0
  25. data/example/images/ruby_app/build_context/example_file.txt +2 -0
  26. data/example/images/ruby_app/image.rb +15 -0
  27. data/example/images/ruby_app2/Dockerfile +8 -0
  28. data/example/images/ruby_app2/build_context/example_file.txt +2 -0
  29. data/example/images/ruby_app2/image.rb +4 -0
  30. data/example/infrastructure/artifacts.rb +13 -0
  31. data/example/infrastructure/env_files.rb +4 -0
  32. data/example/infrastructure/registries.rb +4 -0
  33. data/example/infrastructure/services.rb +3 -0
  34. data/example/infrastructure/templates.rb +4 -0
  35. data/kuber_kit.gemspec +35 -0
  36. data/lib/kuber_kit.rb +205 -0
  37. data/lib/kuber_kit/actions/configuration_loader.rb +74 -0
  38. data/lib/kuber_kit/actions/env_file_reader.rb +17 -0
  39. data/lib/kuber_kit/actions/image_compiler.rb +56 -0
  40. data/lib/kuber_kit/actions/kubectl_applier.rb +17 -0
  41. data/lib/kuber_kit/actions/service_applier.rb +39 -0
  42. data/lib/kuber_kit/actions/service_reader.rb +17 -0
  43. data/lib/kuber_kit/actions/template_reader.rb +17 -0
  44. data/lib/kuber_kit/artifacts_sync/abstract_artifact_resolver.rb +5 -0
  45. data/lib/kuber_kit/artifacts_sync/artifacts_updater.rb +42 -0
  46. data/lib/kuber_kit/artifacts_sync/git_artifact_resolver.rb +31 -0
  47. data/lib/kuber_kit/artifacts_sync/null_artifact_resolver.rb +7 -0
  48. data/lib/kuber_kit/cli.rb +72 -0
  49. data/lib/kuber_kit/configs.rb +42 -0
  50. data/lib/kuber_kit/container.rb +207 -0
  51. data/lib/kuber_kit/core/artifacts/abstract_artifact.rb +13 -0
  52. data/lib/kuber_kit/core/artifacts/artifact_store.rb +45 -0
  53. data/lib/kuber_kit/core/artifacts/git.rb +22 -0
  54. data/lib/kuber_kit/core/artifacts/local.rb +14 -0
  55. data/lib/kuber_kit/core/configuration.rb +20 -0
  56. data/lib/kuber_kit/core/configuration_definition.rb +67 -0
  57. data/lib/kuber_kit/core/configuration_definition_factory.rb +5 -0
  58. data/lib/kuber_kit/core/configuration_factory.rb +61 -0
  59. data/lib/kuber_kit/core/configuration_store.rb +72 -0
  60. data/lib/kuber_kit/core/context_helper/base_helper.rb +28 -0
  61. data/lib/kuber_kit/core/context_helper/context_helper_factory.rb +23 -0
  62. data/lib/kuber_kit/core/context_helper/image_helper.rb +2 -0
  63. data/lib/kuber_kit/core/context_helper/service_helper.rb +19 -0
  64. data/lib/kuber_kit/core/env_files/abstract_env_file.rb +9 -0
  65. data/lib/kuber_kit/core/env_files/artifact_file.rb +9 -0
  66. data/lib/kuber_kit/core/env_files/env_file_store.rb +45 -0
  67. data/lib/kuber_kit/core/image.rb +39 -0
  68. data/lib/kuber_kit/core/image_definition.rb +85 -0
  69. data/lib/kuber_kit/core/image_definition_factory.rb +5 -0
  70. data/lib/kuber_kit/core/image_factory.rb +40 -0
  71. data/lib/kuber_kit/core/image_store.rb +60 -0
  72. data/lib/kuber_kit/core/registries/abstract_registry.rb +25 -0
  73. data/lib/kuber_kit/core/registries/registry.rb +24 -0
  74. data/lib/kuber_kit/core/registries/registry_store.rb +49 -0
  75. data/lib/kuber_kit/core/service.rb +14 -0
  76. data/lib/kuber_kit/core/service_definition.rb +33 -0
  77. data/lib/kuber_kit/core/service_definition_factory.rb +5 -0
  78. data/lib/kuber_kit/core/service_factory.rb +17 -0
  79. data/lib/kuber_kit/core/service_store.rb +68 -0
  80. data/lib/kuber_kit/core/templates/abstract_template.rb +9 -0
  81. data/lib/kuber_kit/core/templates/artifact_file.rb +9 -0
  82. data/lib/kuber_kit/core/templates/template_store.rb +45 -0
  83. data/lib/kuber_kit/env_file_reader/abstract_env_file_reader.rb +5 -0
  84. data/lib/kuber_kit/env_file_reader/artifact_file_reader.rb +86 -0
  85. data/lib/kuber_kit/env_file_reader/reader.rb +35 -0
  86. data/lib/kuber_kit/extensions/colored_string.rb +43 -0
  87. data/lib/kuber_kit/extensions/contracts.rb +4 -0
  88. data/lib/kuber_kit/extensions/indocker_compat.rb +19 -0
  89. data/lib/kuber_kit/extensions/inspectable.rb +10 -0
  90. data/lib/kuber_kit/image_compiler/compiler.rb +21 -0
  91. data/lib/kuber_kit/image_compiler/image_build_dir_creator.rb +37 -0
  92. data/lib/kuber_kit/image_compiler/image_builder.rb +26 -0
  93. data/lib/kuber_kit/image_compiler/image_dependency_resolver.rb +40 -0
  94. data/lib/kuber_kit/image_compiler/version_tag_builder.rb +5 -0
  95. data/lib/kuber_kit/preprocessing/dir_preprocessor.rb +19 -0
  96. data/lib/kuber_kit/preprocessing/file_preprocessor.rb +33 -0
  97. data/lib/kuber_kit/preprocessing/text_preprocessor.rb +7 -0
  98. data/lib/kuber_kit/service_deployer/service_list_resolver.rb +56 -0
  99. data/lib/kuber_kit/service_deployer/service_reader.rb +20 -0
  100. data/lib/kuber_kit/shell/abstract_shell.rb +20 -0
  101. data/lib/kuber_kit/shell/bash_commands.rb +25 -0
  102. data/lib/kuber_kit/shell/command_counter.rb +19 -0
  103. data/lib/kuber_kit/shell/docker_commands.rb +16 -0
  104. data/lib/kuber_kit/shell/git_commands.rb +28 -0
  105. data/lib/kuber_kit/shell/kubectl_commands.rb +12 -0
  106. data/lib/kuber_kit/shell/local_shell.rb +64 -0
  107. data/lib/kuber_kit/shell/rsync_commands.rb +20 -0
  108. data/lib/kuber_kit/template_reader/abstract_template_reader.rb +5 -0
  109. data/lib/kuber_kit/template_reader/artifact_file_reader.rb +14 -0
  110. data/lib/kuber_kit/template_reader/reader.rb +35 -0
  111. data/lib/kuber_kit/tools/file_presence_checker.rb +25 -0
  112. data/lib/kuber_kit/tools/files_sync.rb +10 -0
  113. data/lib/kuber_kit/tools/logger_factory.rb +34 -0
  114. data/lib/kuber_kit/ui.rb +18 -0
  115. data/lib/kuber_kit/ui/interactive.rb +44 -0
  116. data/lib/kuber_kit/ui/simple.rb +75 -0
  117. data/lib/kuber_kit/version.rb +3 -0
  118. metadata +273 -0
@@ -0,0 +1,25 @@
1
+ class KuberKit::Core::Registries::AbstractRegistry
2
+ include KuberKit::Extensions::Inspectable
3
+
4
+ attr_reader :name
5
+
6
+ def initialize(registry_name)
7
+ @name = registry_name
8
+ end
9
+
10
+ def path
11
+ raise KuberKit::NotImplementedError, "must be implemented"
12
+ end
13
+
14
+ def remote_path
15
+ raise KuberKit::NotImplementedError, "must be implemented"
16
+ end
17
+
18
+ def remote?
19
+ raise KuberKit::NotImplementedError, "must be implemented"
20
+ end
21
+
22
+ def local?
23
+ raise KuberKit::NotImplementedError, "must be implemented"
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ class KuberKit::Core::Registries::Registry < KuberKit::Core::Registries::AbstractRegistry
2
+ def set_remote_url(remote_url)
3
+ @remote_url = remote_url
4
+
5
+ self
6
+ end
7
+ alias_method :setup, :set_remote_url
8
+
9
+ def path
10
+ name.to_s
11
+ end
12
+
13
+ def remote_path
14
+ [@remote_url, path].compact.join("/")
15
+ end
16
+
17
+ def remote?
18
+ !local?
19
+ end
20
+
21
+ def local?
22
+ @remote_url.nil?
23
+ end
24
+ end
@@ -0,0 +1,49 @@
1
+ class KuberKit::Core::Registries::RegistryStore
2
+ NotFoundError = Class.new(KuberKit::NotFoundError)
3
+ AlreadyAddedError = Class.new(KuberKit::Error)
4
+
5
+ def add(registry)
6
+ @@registries ||= {}
7
+
8
+ if !registry.is_a?(KuberKit::Core::Registries::AbstractRegistry)
9
+ raise ArgumentError.new("should be an instance of KuberKit::Core::Registries::AbstractRegistry, got: #{registry.inspect}")
10
+ end
11
+
12
+ unless @@registries[registry.name].nil?
13
+ raise AlreadyAddedError, "registry #{registry.name} was already added"
14
+ end
15
+
16
+ @@registries[registry.name] = registry
17
+ end
18
+
19
+ def get(registry_name)
20
+ registry = get_from_configuration(registry_name) ||
21
+ get_global(registry_name)
22
+
23
+ registry
24
+ end
25
+
26
+ def get_global(registry_name)
27
+ @@registries ||= {}
28
+ registry = @@registries[registry_name]
29
+
30
+ if registry.nil?
31
+ raise NotFoundError, "registry '#{registry_name}' not found"
32
+ end
33
+
34
+ registry
35
+ end
36
+
37
+ def get_from_configuration(registry_name)
38
+ registries = KuberKit.current_configuration.registries
39
+ registries[registry_name]
40
+ end
41
+
42
+ def default_registry
43
+ @default_registry ||= KuberKit::Core::Registries::Registry.new(:default)
44
+ end
45
+
46
+ def reset!
47
+ @@registries = {}
48
+ end
49
+ end
@@ -0,0 +1,14 @@
1
+ class KuberKit::Core::Service
2
+ attr_reader :name, :template_name, :tags
3
+
4
+ Contract KeywordArgs[
5
+ name: Symbol,
6
+ template_name: Symbol,
7
+ tags: ArrayOf[Symbol],
8
+ ] => Any
9
+ def initialize(name:, template_name:, tags:)
10
+ @name = name
11
+ @template_name = template_name
12
+ @tags = tags
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ class KuberKit::Core::ServiceDefinition
2
+ attr_reader :service_name, :template_name
3
+
4
+ Contract Or[Symbol, String] => Any
5
+ def initialize(service_name)
6
+ @service_name = service_name.to_sym
7
+ end
8
+
9
+ def to_service_attrs
10
+ OpenStruct.new(
11
+ name: @service_name,
12
+ template_name: get_value(@template_name),
13
+ tags: Array(get_value(@tags)).map(&:to_sym)
14
+ )
15
+ end
16
+
17
+ def template(value = nil, &block)
18
+ @template_name = block_given? ? block : value
19
+
20
+ self
21
+ end
22
+
23
+ def tags(*value, &block)
24
+ @tags = block_given? ? block : Array(value).flatten
25
+
26
+ self
27
+ end
28
+
29
+ private
30
+ def get_value(variable)
31
+ variable.is_a?(Proc) ? variable.call : variable
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ class KuberKit::Core::ServiceDefinitionFactory
2
+ def create(service_name)
3
+ KuberKit::Core::ServiceDefinition.new(service_name)
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ class KuberKit::Core::ServiceFactory
2
+ AttributeNotSetError = Class.new(KuberKit::Error)
3
+
4
+ def create(definition)
5
+ service_attrs = definition.to_service_attrs
6
+
7
+ if service_attrs.template_name.nil?
8
+ raise AttributeNotSetError, "Please set template for service using #template method"
9
+ end
10
+
11
+ KuberKit::Core::Service.new(
12
+ name: service_attrs.name,
13
+ template_name: service_attrs.template_name,
14
+ tags: service_attrs.tags
15
+ )
16
+ end
17
+ end
@@ -0,0 +1,68 @@
1
+ class KuberKit::Core::ServiceStore
2
+ NotFoundError = Class.new(KuberKit::Error)
3
+ AlreadyAddedError = Class.new(KuberKit::Error)
4
+
5
+ include KuberKit::Import[
6
+ "core.service_factory",
7
+ "core.service_definition_factory",
8
+ "shell.local_shell"
9
+ ]
10
+
11
+ def define(service_name)
12
+ definition = service_definition_factory.create(service_name)
13
+ add_definition(definition)
14
+ definition
15
+ end
16
+
17
+ def add_definition(service_definition)
18
+ @@service_definitions ||= {}
19
+
20
+ unless @@service_definitions[service_definition.service_name].nil?
21
+ raise AlreadyAddedError, "service #{service_definition.service_name} was already added"
22
+ end
23
+
24
+ @@service_definitions[service_definition.service_name] = service_definition
25
+ end
26
+
27
+ def get_definition(service_name)
28
+ @@service_definitions ||= {}
29
+
30
+ if @@service_definitions[service_name].nil?
31
+ raise NotFoundError, "service '#{service_name}' not found"
32
+ end
33
+
34
+ @@service_definitions[service_name]
35
+ end
36
+
37
+ def get_service(service_name)
38
+ definition = get_definition(service_name)
39
+
40
+ service_factory.create(definition)
41
+ end
42
+
43
+ def load_definitions(dir_path)
44
+ files = local_shell.recursive_list_files(dir_path, name: "*.rb").each do |path|
45
+ load_definition(path)
46
+ end
47
+ end
48
+
49
+ def load_definition(file_path)
50
+ require(file_path)
51
+ end
52
+
53
+ def reset!
54
+ @@service_definitions = {}
55
+ end
56
+
57
+ def all_definitions
58
+ @@service_definitions ||= {}
59
+ end
60
+
61
+ def count
62
+ all_definitions.count
63
+ end
64
+
65
+ def exists?(service_name)
66
+ !all_definitions[service_name].nil?
67
+ end
68
+ end
@@ -0,0 +1,9 @@
1
+ class KuberKit::Core::Templates::AbstractTemplate
2
+ include KuberKit::Extensions::Inspectable
3
+
4
+ attr_reader :name
5
+
6
+ def initialize(template_name)
7
+ @name = template_name
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class KuberKit::Core::Templates::ArtifactFile < KuberKit::Core::Templates::AbstractTemplate
2
+ attr_reader :artifact_name, :file_path
3
+
4
+ def initialize(template_name, artifact_name:, file_path:)
5
+ super(template_name)
6
+ @artifact_name = artifact_name
7
+ @file_path = file_path
8
+ end
9
+ end
@@ -0,0 +1,45 @@
1
+ class KuberKit::Core::Templates::TemplateStore
2
+ NotFoundError = Class.new(KuberKit::NotFoundError)
3
+ AlreadyAddedError = Class.new(KuberKit::Error)
4
+
5
+ def add(template)
6
+ @@templates ||= {}
7
+
8
+ if !template.is_a?(KuberKit::Core::Templates::AbstractTemplate)
9
+ raise ArgumentError.new("should be an instance of KuberKit::Core::Templates::AbstractTemplate, got: #{template.inspect}")
10
+ end
11
+
12
+ unless @@templates[template.name].nil?
13
+ raise AlreadyAddedError, "template #{template.name} was already added"
14
+ end
15
+
16
+ @@templates[template.name] = template
17
+ end
18
+
19
+ def get(template_name)
20
+ template = get_from_configuration(template_name) ||
21
+ get_global(template_name)
22
+
23
+ template
24
+ end
25
+
26
+ def get_global(template_name)
27
+ @@templates ||= {}
28
+ template = @@templates[template_name]
29
+
30
+ if template.nil?
31
+ raise NotFoundError, "template '#{template_name}' not found"
32
+ end
33
+
34
+ template
35
+ end
36
+
37
+ def get_from_configuration(template_name)
38
+ templates = KuberKit.current_configuration.templates
39
+ templates[template_name]
40
+ end
41
+
42
+ def reset!
43
+ @@templates = {}
44
+ end
45
+ end
@@ -0,0 +1,5 @@
1
+ class KuberKit::EnvFileReader::AbstractEnvFileReader
2
+ def read(shell, env_file)
3
+ raise KuberKit::NotImplementedError, "must be implemented"
4
+ end
5
+ end
@@ -0,0 +1,86 @@
1
+ class KuberKit::EnvFileReader::ArtifactFileReader < KuberKit::EnvFileReader::AbstractEnvFileReader
2
+ include KuberKit::Import[
3
+ "core.artifact_store"
4
+ ]
5
+
6
+ def read(shell, env_file)
7
+ artifact = artifact_store.get(env_file.artifact_name)
8
+
9
+ file_parts = [artifact.cloned_path, env_file.file_path].compact
10
+ file_path = File.join(*file_parts)
11
+
12
+ read_file(shell, file_path)
13
+ end
14
+
15
+ private
16
+ def read_file(shell, file_path)
17
+ result = {}
18
+ content = shell.read(file_path)
19
+ Parser.call(content)
20
+ end
21
+
22
+ # Parser is based on:
23
+ # https://github.com/bkeepers/dotenv/blob/master/lib/dotenv/parser.rb
24
+ class Parser
25
+ LINE = /
26
+ (?:^|\A) # beginning of line
27
+ \s* # leading whitespace
28
+ (?:export\s+)? # optional export
29
+ ([\w\.]+) # key
30
+ (?:\s*=\s*?|:\s+?) # separator
31
+ ( # optional value begin
32
+ \s*'(?:\\'|[^'])*' # single quoted value
33
+ | # or
34
+ \s*"(?:\\"|[^"])*" # double quoted value
35
+ | # or
36
+ [^\#\r\n]+ # unquoted value
37
+ )? # value end
38
+ \s* # trailing whitespace
39
+ (?:\#.*)? # optional comment
40
+ (?:$|\z) # end of line
41
+ /x
42
+
43
+ class << self
44
+ def call(string, is_load = false)
45
+ new(string, is_load).call
46
+ end
47
+ end
48
+
49
+ def initialize(string, is_load = false)
50
+ @string = string
51
+ @hash = {}
52
+ @is_load = is_load
53
+ end
54
+
55
+ def call
56
+ # Convert line breaks to same format
57
+ lines = @string.gsub(/\r\n?/, "\n")
58
+ # Process matches
59
+ lines.scan(LINE).each do |key, value|
60
+ @hash[key] = parse_value(value || "")
61
+ end
62
+ @hash
63
+ end
64
+
65
+ private
66
+
67
+ def parse_value(value)
68
+ # Remove surrounding quotes
69
+ value = value.strip.sub(/\A(['"])(.*)\1\z/m, '\2')
70
+
71
+ if Regexp.last_match(1) == '"'
72
+ value = unescape_characters(expand_newlines(value))
73
+ end
74
+
75
+ value
76
+ end
77
+
78
+ def unescape_characters(value)
79
+ value.gsub(/\\([^$])/, '\1')
80
+ end
81
+
82
+ def expand_newlines(value)
83
+ value.gsub('\n', "\n").gsub('\r', "\r")
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,35 @@
1
+ class KuberKit::EnvFileReader::Reader
2
+ ReaderNotFoundError = Class.new(KuberKit::NotFoundError)
3
+
4
+ include KuberKit::Import[
5
+ "env_file_reader.artifact_file_reader",
6
+ ]
7
+
8
+ def use_reader(env_file_reader, env_file_class:)
9
+ @@readers ||= {}
10
+
11
+ if !env_file_reader.is_a?(KuberKit::EnvFileReader::AbstractEnvFileReader)
12
+ raise ArgumentError.new("should be an instance of KuberKit::EnvFileReader::AbstractEnvFileReader, got: #{env_file_reader.inspect}")
13
+ end
14
+
15
+ @@readers[env_file_class] = env_file_reader
16
+ end
17
+
18
+ def read(shell, env_file)
19
+ add_default_readers
20
+
21
+ reader = @@readers[env_file.class]
22
+
23
+ raise ReaderNotFoundError, "Can't find reader for env file #{env_file}" if reader.nil?
24
+
25
+ reader.read(shell, env_file)
26
+ end
27
+
28
+ def add_default_readers
29
+ use_reader(artifact_file_reader, env_file_class: KuberKit::Core::EnvFiles::ArtifactFile)
30
+ end
31
+
32
+ def reset!
33
+ @@readers = {}
34
+ end
35
+ end
@@ -0,0 +1,43 @@
1
+ class String
2
+ module Colors
3
+ RED = 31
4
+ GREEN = 32
5
+ YELLOW = 33
6
+ BLUE = 34
7
+ PURPLE = 35
8
+ CYAN = 36
9
+ GREY = 37
10
+ end
11
+
12
+ def red
13
+ colorize(Colors::RED)
14
+ end
15
+
16
+ def green
17
+ colorize(Colors::GREEN)
18
+ end
19
+
20
+ def yellow
21
+ colorize(Colors::YELLOW)
22
+ end
23
+
24
+ def blue
25
+ colorize(Colors::BLUE)
26
+ end
27
+
28
+ def purple
29
+ colorize(Colors::PURPLE)
30
+ end
31
+
32
+ def cyan
33
+ colorize(Colors::CYAN)
34
+ end
35
+
36
+ def grey
37
+ colorize(Colors::GREY)
38
+ end
39
+
40
+ def colorize(color_code)
41
+ "\e[#{color_code}m#{self}\e[0m"
42
+ end
43
+ end