kuber_kit 0.1.0

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