kuber_kit 0.5.1 → 0.5.6
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 +4 -4
- data/CHANGELOG.md +21 -0
- data/Gemfile.lock +5 -5
- data/TODO.md +5 -5
- data/example/configurations/review.rb +1 -1
- data/example/services/docker_app.rb +2 -1
- data/example/services/env_file.rb +1 -1
- data/example/services/ruby_app.rb +2 -1
- data/lib/kuber_kit.rb +10 -0
- data/lib/kuber_kit/actions/kubectl_get.rb +32 -0
- data/lib/kuber_kit/actions/service_checker.rb +5 -0
- data/lib/kuber_kit/actions/service_deployer.rb +85 -61
- data/lib/kuber_kit/cli.rb +14 -3
- data/lib/kuber_kit/configs.rb +10 -6
- data/lib/kuber_kit/container.rb +20 -0
- data/lib/kuber_kit/core/artifacts/artifact_store.rb +3 -0
- data/lib/kuber_kit/core/configuration.rb +4 -2
- data/lib/kuber_kit/core/configuration_definition.rb +7 -0
- data/lib/kuber_kit/core/configuration_factory.rb +1 -0
- data/lib/kuber_kit/core/dependencies/abstract_dependency_resolver.rb +75 -0
- data/lib/kuber_kit/core/env_files/abstract_env_file.rb +4 -0
- data/lib/kuber_kit/core/env_files/artifact_file.rb +4 -0
- data/lib/kuber_kit/core/env_files/env_file_store.rb +3 -0
- data/lib/kuber_kit/core/env_files/env_group.rb +12 -0
- data/lib/kuber_kit/core/image.rb +2 -1
- data/lib/kuber_kit/core/registries/registry_store.rb +3 -0
- data/lib/kuber_kit/core/service.rb +4 -2
- data/lib/kuber_kit/core/service_definition.rb +13 -6
- data/lib/kuber_kit/core/service_factory.rb +1 -0
- data/lib/kuber_kit/core/templates/template_store.rb +3 -0
- data/lib/kuber_kit/env_file_reader/env_file_parser.rb +51 -0
- data/lib/kuber_kit/env_file_reader/env_file_tempfile_creator.rb +17 -0
- data/lib/kuber_kit/env_file_reader/reader.rb +2 -0
- data/lib/kuber_kit/env_file_reader/strategies/artifact_file.rb +9 -65
- data/lib/kuber_kit/env_file_reader/strategies/env_group.rb +21 -0
- data/lib/kuber_kit/image_compiler/image_dependency_resolver.rb +5 -53
- data/lib/kuber_kit/service_deployer/service_dependency_resolver.rb +14 -0
- data/lib/kuber_kit/service_deployer/service_list_resolver.rb +11 -6
- data/lib/kuber_kit/service_deployer/strategies/docker.rb +31 -12
- data/lib/kuber_kit/service_deployer/strategies/kubernetes.rb +9 -2
- data/lib/kuber_kit/shell/commands/kubectl_commands.rb +8 -0
- data/lib/kuber_kit/shell/local_shell.rb +15 -1
- data/lib/kuber_kit/template_reader/strategies/artifact_file.rb +3 -3
- data/lib/kuber_kit/tools/logger_factory.rb +14 -0
- data/lib/kuber_kit/version.rb +1 -1
- metadata +10 -2
data/lib/kuber_kit/configs.rb
CHANGED
@@ -4,8 +4,8 @@ class KuberKit::Configs
|
|
4
4
|
AVAILABLE_CONFIGS = [
|
5
5
|
:image_dockerfile_name, :image_build_context_dir, :image_tag, :docker_ignore_list, :image_compile_dir,
|
6
6
|
:kuber_kit_dirname, :kuber_kit_min_version, :images_dirname, :services_dirname, :infra_dirname, :configurations_dirname,
|
7
|
-
:artifact_clone_dir, :service_config_dir, :deployer_strategy, :compile_simultaneous_limit,
|
8
|
-
:additional_images_paths, :deprecation_warnings_disabled, :log_file_path
|
7
|
+
:artifact_clone_dir, :service_config_dir, :deployer_strategy, :compile_simultaneous_limit, :deploy_simultaneous_limit,
|
8
|
+
:additional_images_paths, :deprecation_warnings_disabled, :log_file_path, :env_file_compile_dir
|
9
9
|
]
|
10
10
|
DOCKER_IGNORE_LIST = [
|
11
11
|
'Dockerfile',
|
@@ -34,10 +34,12 @@ class KuberKit::Configs
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def add_default_configs
|
37
|
+
home_kuber_kit_path = File.expand_path(File.join("~", ".kuber_kit"))
|
38
|
+
|
37
39
|
set :image_dockerfile_name, "Dockerfile"
|
38
40
|
set :image_build_context_dir, "build_context"
|
39
41
|
set :image_tag, 'latest'
|
40
|
-
set :image_compile_dir, "
|
42
|
+
set :image_compile_dir, File.join(home_kuber_kit_path, "image_builds")
|
41
43
|
set :docker_ignore_list, DOCKER_IGNORE_LIST
|
42
44
|
set :kuber_kit_dirname, "kuber_kit"
|
43
45
|
set :kuber_kit_min_version, KuberKit::VERSION
|
@@ -45,13 +47,15 @@ class KuberKit::Configs
|
|
45
47
|
set :services_dirname, "services"
|
46
48
|
set :infra_dirname, "infrastructure"
|
47
49
|
set :configurations_dirname, "configurations"
|
48
|
-
set :artifact_clone_dir, "
|
49
|
-
set :service_config_dir, "
|
50
|
+
set :artifact_clone_dir, File.join(home_kuber_kit_path, "artifacts")
|
51
|
+
set :service_config_dir, File.join(home_kuber_kit_path, "services")
|
50
52
|
set :deployer_strategy, :kubernetes
|
51
53
|
set :compile_simultaneous_limit, 5
|
54
|
+
set :deploy_simultaneous_limit, 5
|
52
55
|
set :additional_images_paths, []
|
53
56
|
set :deprecation_warnings_disabled, false
|
54
|
-
set :log_file_path, "
|
57
|
+
set :log_file_path, File.join(home_kuber_kit_path, "deploy.log")
|
58
|
+
set :env_file_compile_dir, File.join(home_kuber_kit_path, "env_files")
|
55
59
|
end
|
56
60
|
|
57
61
|
def items
|
data/lib/kuber_kit/container.rb
CHANGED
@@ -45,6 +45,10 @@ class KuberKit::Container
|
|
45
45
|
KuberKit::Actions::KubectlDescribe.new
|
46
46
|
end
|
47
47
|
|
48
|
+
register "actions.kubectl_get" do
|
49
|
+
KuberKit::Actions::KubectlGet.new
|
50
|
+
end
|
51
|
+
|
48
52
|
register "actions.kubectl_logs" do
|
49
53
|
KuberKit::Actions::KubectlLogs.new
|
50
54
|
end
|
@@ -225,10 +229,22 @@ class KuberKit::Container
|
|
225
229
|
KuberKit::EnvFileReader::Reader.new
|
226
230
|
end
|
227
231
|
|
232
|
+
register "env_file_reader.env_file_parser" do
|
233
|
+
KuberKit::EnvFileReader::EnvFileParser.new
|
234
|
+
end
|
235
|
+
|
236
|
+
register "env_file_reader.env_file_tempfile_creator" do
|
237
|
+
KuberKit::EnvFileReader::EnvFileTempfileCreator.new
|
238
|
+
end
|
239
|
+
|
228
240
|
register "env_file_reader.strategies.artifact_file" do
|
229
241
|
KuberKit::EnvFileReader::Strategies::ArtifactFile.new
|
230
242
|
end
|
231
243
|
|
244
|
+
register "env_file_reader.strategies.env_group" do
|
245
|
+
KuberKit::EnvFileReader::Strategies::EnvGroup.new
|
246
|
+
end
|
247
|
+
|
232
248
|
register "template_reader.action_handler" do
|
233
249
|
KuberKit::TemplateReader::ActionHandler.new
|
234
250
|
end
|
@@ -257,6 +273,10 @@ class KuberKit::Container
|
|
257
273
|
KuberKit::ServiceDeployer::ServiceListResolver.new
|
258
274
|
end
|
259
275
|
|
276
|
+
register "service_deployer.service_dependency_resolver" do
|
277
|
+
KuberKit::ServiceDeployer::ServiceDependencyResolver.new
|
278
|
+
end
|
279
|
+
|
260
280
|
register "service_deployer.strategies.kubernetes" do
|
261
281
|
KuberKit::ServiceDeployer::Strategies::Kubernetes.new
|
262
282
|
end
|
@@ -3,6 +3,7 @@ class KuberKit::Core::Artifacts::ArtifactStore
|
|
3
3
|
store.add(artifact.name, artifact)
|
4
4
|
end
|
5
5
|
|
6
|
+
Contract Symbol => Maybe[KuberKit::Core::Artifacts::AbstractArtifact]
|
6
7
|
def get(artifact_name)
|
7
8
|
artifact = get_from_configuration(artifact_name) ||
|
8
9
|
get_global(artifact_name)
|
@@ -10,10 +11,12 @@ class KuberKit::Core::Artifacts::ArtifactStore
|
|
10
11
|
artifact
|
11
12
|
end
|
12
13
|
|
14
|
+
Contract Symbol => Maybe[KuberKit::Core::Artifacts::AbstractArtifact]
|
13
15
|
def get_global(artifact_name)
|
14
16
|
store.get(artifact_name)
|
15
17
|
end
|
16
18
|
|
19
|
+
Contract Symbol => Maybe[KuberKit::Core::Artifacts::AbstractArtifact]
|
17
20
|
def get_from_configuration(artifact_name)
|
18
21
|
artifacts = KuberKit.current_configuration.artifacts
|
19
22
|
artifacts[artifact_name]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class KuberKit::Core::Configuration
|
2
2
|
attr_reader :name, :artifacts, :registries, :env_files, :templates, :kubeconfig_path,
|
3
|
-
:services_attributes, :enabled_services, :build_servers, :global_build_vars,
|
3
|
+
:services_attributes, :enabled_services, :disabled_services, :build_servers, :global_build_vars,
|
4
4
|
:deployer_strategy, :deployer_namespace, :deployer_require_confirimation
|
5
5
|
|
6
6
|
Contract KeywordArgs[
|
@@ -12,6 +12,7 @@ class KuberKit::Core::Configuration
|
|
12
12
|
kubeconfig_path: Maybe[String],
|
13
13
|
services_attributes: HashOf[Symbol => Hash],
|
14
14
|
enabled_services: ArrayOf[Symbol],
|
15
|
+
disabled_services: ArrayOf[Symbol],
|
15
16
|
build_servers: ArrayOf[KuberKit::Core::BuildServers::AbstractBuildServer],
|
16
17
|
global_build_vars: HashOf[Symbol => Any],
|
17
18
|
deployer_strategy: Symbol,
|
@@ -19,7 +20,7 @@ class KuberKit::Core::Configuration
|
|
19
20
|
deployer_require_confirimation: Bool,
|
20
21
|
] => Any
|
21
22
|
def initialize(name:, artifacts:, registries:, env_files:, templates:, kubeconfig_path:,
|
22
|
-
services_attributes:, enabled_services:, build_servers:, global_build_vars:,
|
23
|
+
services_attributes:, enabled_services:, disabled_services:, build_servers:, global_build_vars:,
|
23
24
|
deployer_strategy:, deployer_namespace:, deployer_require_confirimation:)
|
24
25
|
@name = name
|
25
26
|
@artifacts = artifacts
|
@@ -30,6 +31,7 @@ class KuberKit::Core::Configuration
|
|
30
31
|
@build_servers = build_servers
|
31
32
|
@services_attributes = services_attributes
|
32
33
|
@enabled_services = enabled_services
|
34
|
+
@disabled_services = disabled_services
|
33
35
|
@global_build_vars = global_build_vars
|
34
36
|
@deployer_strategy = deployer_strategy
|
35
37
|
@deployer_namespace = deployer_namespace
|
@@ -12,6 +12,7 @@ class KuberKit::Core::ConfigurationDefinition
|
|
12
12
|
@templates = {}
|
13
13
|
@build_servers = []
|
14
14
|
@enabled_services = []
|
15
|
+
@disabled_services = []
|
15
16
|
@services_attributes = {}
|
16
17
|
end
|
17
18
|
|
@@ -24,6 +25,7 @@ class KuberKit::Core::ConfigurationDefinition
|
|
24
25
|
templates: @templates,
|
25
26
|
kubeconfig_path: @kubeconfig_path,
|
26
27
|
enabled_services: @enabled_services,
|
28
|
+
disabled_services: @disabled_services,
|
27
29
|
build_servers: @build_servers,
|
28
30
|
services_attributes: @services_attributes,
|
29
31
|
global_build_vars: @global_build_vars,
|
@@ -116,6 +118,11 @@ class KuberKit::Core::ConfigurationDefinition
|
|
116
118
|
raise KuberKit::Error, "#enabled_services method accepts only Array or Hash"
|
117
119
|
end
|
118
120
|
|
121
|
+
def disabled_services(services)
|
122
|
+
@disabled_services += services.map(&:to_sym)
|
123
|
+
return self
|
124
|
+
end
|
125
|
+
|
119
126
|
def service_attributes(services)
|
120
127
|
@services_attributes = @services_attributes.merge(services)
|
121
128
|
self
|
@@ -29,6 +29,7 @@ class KuberKit::Core::ConfigurationFactory
|
|
29
29
|
build_servers: build_servers,
|
30
30
|
services_attributes: configuration_attrs.services_attributes,
|
31
31
|
enabled_services: configuration_attrs.enabled_services,
|
32
|
+
disabled_services: configuration_attrs.disabled_services,
|
32
33
|
global_build_vars: configuration_attrs.global_build_vars || {},
|
33
34
|
deployer_strategy: configuration_attrs.deployer_strategy || configs.deployer_strategy,
|
34
35
|
deployer_namespace: configuration_attrs.deployer_namespace,
|
@@ -0,0 +1,75 @@
|
|
1
|
+
class KuberKit::Core::Dependencies::AbstractDependencyResolver
|
2
|
+
CircularDependencyError = Class.new(KuberKit::Error)
|
3
|
+
DependencyNotFoundError = Class.new(KuberKit::NotFoundError)
|
4
|
+
|
5
|
+
# Iterate over list of dependencies for items (including the items themself).
|
6
|
+
# Iteration will send the list to the callback block function
|
7
|
+
Contract Or[Symbol, ArrayOf[Symbol]], Proc => Any
|
8
|
+
def each_with_deps(item_names, &block)
|
9
|
+
resolved_dependencies = []
|
10
|
+
# Get first list of dependencies ready to resolve
|
11
|
+
next_dependencies = get_next(item_names, limit: dependency_batch_size)
|
12
|
+
|
13
|
+
# Call the block for each list of dependencies ready to resolve, then calculate the next list
|
14
|
+
while (next_dependencies - resolved_dependencies).any?
|
15
|
+
block.call(next_dependencies)
|
16
|
+
resolved_dependencies += next_dependencies
|
17
|
+
next_dependencies = get_next(item_names, resolved: resolved_dependencies, limit: dependency_batch_size)
|
18
|
+
end
|
19
|
+
|
20
|
+
(item_names - resolved_dependencies).each_slice(dependency_batch_size) do |group|
|
21
|
+
block.call(group)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns next list of dependencies ready to resolve.
|
26
|
+
# Item is not ready to resolve if it has personal dependency.
|
27
|
+
# E.g. if "A" depends on "B" and "C", "C" depends on "D", then only "B" and "D" will be returned.
|
28
|
+
Contract Or[Symbol, ArrayOf[Symbol]], KeywordArgs[
|
29
|
+
resolved: Optional[ArrayOf[Symbol]],
|
30
|
+
limit: Optional[Maybe[Num]]
|
31
|
+
] => Any
|
32
|
+
def get_next(item_names, resolved: [], limit: nil)
|
33
|
+
deps = Array(item_names).map { |i| get_recursive_deps(i) }.flatten.uniq
|
34
|
+
|
35
|
+
# Find out which dependencies are ready to resolve,
|
36
|
+
# they should not have unresolved personal dependencies
|
37
|
+
ready_to_resolve = deps.select do |dep_name|
|
38
|
+
unresolved_deps = get_deps(dep_name) - resolved
|
39
|
+
unresolved_deps.empty?
|
40
|
+
end
|
41
|
+
unresolved_deps = ready_to_resolve - resolved
|
42
|
+
unresolved_deps = unresolved_deps.take(limit) if limit
|
43
|
+
unresolved_deps
|
44
|
+
end
|
45
|
+
|
46
|
+
# Get all dependencies for items (including the items themself), without any limitations
|
47
|
+
Contract Or[Symbol, ArrayOf[Symbol]] => Any
|
48
|
+
def get_all(item_names)
|
49
|
+
deps = Array(item_names).map { |i| get_recursive_deps(i) }.flatten
|
50
|
+
(deps + item_names).uniq
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_recursive_deps(item_name, dependency_tree: [])
|
54
|
+
deps = get_deps(item_name)
|
55
|
+
|
56
|
+
if dependency_tree.include?(item_name)
|
57
|
+
raise CircularDependencyError, "Circular dependency found for #{item_name}. Dependency tree: #{dependency_tree.inspect}"
|
58
|
+
end
|
59
|
+
|
60
|
+
child_deps = []
|
61
|
+
deps.each do |i|
|
62
|
+
child_deps += get_recursive_deps(i, dependency_tree: dependency_tree + [item_name])
|
63
|
+
end
|
64
|
+
|
65
|
+
(deps + child_deps).uniq
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_deps(item_name)
|
69
|
+
raise "This method should be overriden"
|
70
|
+
end
|
71
|
+
|
72
|
+
def dependency_batch_size
|
73
|
+
raise "This method should be overriden"
|
74
|
+
end
|
75
|
+
end
|
@@ -3,6 +3,7 @@ class KuberKit::Core::EnvFiles::EnvFileStore
|
|
3
3
|
store.add(env_file.name, env_file)
|
4
4
|
end
|
5
5
|
|
6
|
+
Contract Symbol => Maybe[KuberKit::Core::EnvFiles::AbstractEnvFile]
|
6
7
|
def get(env_file_name)
|
7
8
|
env_file = get_from_configuration(env_file_name) ||
|
8
9
|
get_global(env_file_name)
|
@@ -10,10 +11,12 @@ class KuberKit::Core::EnvFiles::EnvFileStore
|
|
10
11
|
env_file
|
11
12
|
end
|
12
13
|
|
14
|
+
Contract Symbol => Maybe[KuberKit::Core::EnvFiles::AbstractEnvFile]
|
13
15
|
def get_global(env_file_name)
|
14
16
|
store.get(env_file_name)
|
15
17
|
end
|
16
18
|
|
19
|
+
Contract Symbol => Maybe[KuberKit::Core::EnvFiles::AbstractEnvFile]
|
17
20
|
def get_from_configuration(env_file_name)
|
18
21
|
env_files = KuberKit.current_configuration.env_files
|
19
22
|
env_files[env_file_name]
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class KuberKit::Core::EnvFiles::EnvGroup < KuberKit::Core::EnvFiles::AbstractEnvFile
|
2
|
+
attr_reader :env_files
|
3
|
+
|
4
|
+
def initialize(env_group_name, env_files:)
|
5
|
+
super(env_group_name)
|
6
|
+
@env_files = env_files
|
7
|
+
end
|
8
|
+
|
9
|
+
def uniq_name
|
10
|
+
"env-group-#{@name.to_s}"
|
11
|
+
end
|
12
|
+
end
|
data/lib/kuber_kit/core/image.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
class KuberKit::Core::Image
|
2
|
-
attr_reader :name, :dependencies, :registry, :dockerfile_path, :build_vars, :build_context_dir, :tag,
|
2
|
+
attr_reader :name, :dependencies, :registry, :dockerfile_path, :build_vars, :build_context_dir, :tag,
|
3
|
+
:before_build_callback, :after_build_callback
|
3
4
|
|
4
5
|
Contract KeywordArgs[
|
5
6
|
name: Symbol,
|
@@ -3,6 +3,7 @@ class KuberKit::Core::Registries::RegistryStore
|
|
3
3
|
store.add(registry.name, registry)
|
4
4
|
end
|
5
5
|
|
6
|
+
Contract Symbol => Maybe[KuberKit::Core::Registries::AbstractRegistry]
|
6
7
|
def get(registry_name)
|
7
8
|
registry = get_from_configuration(registry_name) ||
|
8
9
|
get_global(registry_name)
|
@@ -10,10 +11,12 @@ class KuberKit::Core::Registries::RegistryStore
|
|
10
11
|
registry
|
11
12
|
end
|
12
13
|
|
14
|
+
Contract Symbol => Maybe[KuberKit::Core::Registries::AbstractRegistry]
|
13
15
|
def get_global(registry_name)
|
14
16
|
store.get(registry_name)
|
15
17
|
end
|
16
18
|
|
19
|
+
Contract Symbol => Maybe[KuberKit::Core::Registries::AbstractRegistry]
|
17
20
|
def get_from_configuration(registry_name)
|
18
21
|
registries = KuberKit.current_configuration.registries
|
19
22
|
registries[registry_name]
|
@@ -1,18 +1,20 @@
|
|
1
1
|
class KuberKit::Core::Service
|
2
2
|
AttributeNotSet = Class.new(Indocker::Error)
|
3
3
|
|
4
|
-
attr_reader :name, :template_name, :tags, :images, :attributes, :deployer_strategy
|
4
|
+
attr_reader :name, :dependencies, :template_name, :tags, :images, :attributes, :deployer_strategy
|
5
5
|
|
6
6
|
Contract KeywordArgs[
|
7
7
|
name: Symbol,
|
8
|
+
dependencies: ArrayOf[Symbol],
|
8
9
|
template_name: Maybe[Symbol],
|
9
10
|
tags: ArrayOf[Symbol],
|
10
11
|
images: ArrayOf[Symbol],
|
11
12
|
attributes: HashOf[Symbol => Any],
|
12
13
|
deployer_strategy: Maybe[Symbol]
|
13
14
|
] => Any
|
14
|
-
def initialize(name:, template_name:, tags:, images:, attributes:, deployer_strategy:)
|
15
|
+
def initialize(name:, dependencies:, template_name:, tags:, images:, attributes:, deployer_strategy:)
|
15
16
|
@name = name
|
17
|
+
@dependencies = dependencies
|
16
18
|
@template_name = template_name
|
17
19
|
@tags = tags
|
18
20
|
@images = images
|
@@ -1,22 +1,29 @@
|
|
1
1
|
class KuberKit::Core::ServiceDefinition
|
2
|
-
attr_reader :service_name, :template_name
|
2
|
+
attr_reader :service_name, :template_name, :dependencies
|
3
3
|
|
4
4
|
Contract Or[Symbol, String] => Any
|
5
5
|
def initialize(service_name)
|
6
6
|
@service_name = service_name.to_sym
|
7
|
+
@dependencies = []
|
7
8
|
end
|
8
9
|
|
9
10
|
def to_service_attrs
|
10
11
|
OpenStruct.new(
|
11
|
-
name:
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
name: @service_name,
|
13
|
+
dependencies: @dependencies,
|
14
|
+
template_name: get_value(@template_name),
|
15
|
+
tags: Array(get_value(@tags)).map(&:to_sym),
|
16
|
+
images: Array(get_value(@images)).map(&:to_sym),
|
17
|
+
attributes: get_value(@attributes),
|
16
18
|
deployer_strategy: get_value(@deployer_strategy),
|
17
19
|
)
|
18
20
|
end
|
19
21
|
|
22
|
+
def depends_on(*value, &block)
|
23
|
+
@dependencies = Array(value).flatten
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
20
27
|
def template(value = nil, &block)
|
21
28
|
@template_name = block_given? ? block : value
|
22
29
|
|
@@ -3,6 +3,7 @@ class KuberKit::Core::Templates::TemplateStore
|
|
3
3
|
store.add(template.name, template)
|
4
4
|
end
|
5
5
|
|
6
|
+
Contract Symbol => Maybe[KuberKit::Core::Templates::AbstractTemplate]
|
6
7
|
def get(template_name)
|
7
8
|
template = get_from_configuration(template_name) ||
|
8
9
|
get_global(template_name)
|
@@ -10,10 +11,12 @@ class KuberKit::Core::Templates::TemplateStore
|
|
10
11
|
template
|
11
12
|
end
|
12
13
|
|
14
|
+
Contract Symbol => Maybe[KuberKit::Core::Templates::AbstractTemplate]
|
13
15
|
def get_global(template_name)
|
14
16
|
store.get(template_name)
|
15
17
|
end
|
16
18
|
|
19
|
+
Contract Symbol => Maybe[KuberKit::Core::Templates::AbstractTemplate]
|
17
20
|
def get_from_configuration(template_name)
|
18
21
|
templates = KuberKit.current_configuration.templates
|
19
22
|
templates[template_name]
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class KuberKit::EnvFileReader::EnvFileParser
|
2
|
+
# Parser is based on:
|
3
|
+
# https://github.com/bkeepers/dotenv/blob/master/lib/dotenv/parser.rb
|
4
|
+
LINE = /
|
5
|
+
(?:^|\A) # beginning of line
|
6
|
+
\s* # leading whitespace
|
7
|
+
(?:export\s+)? # optional export
|
8
|
+
([\w\.]+) # key
|
9
|
+
(?:\s*=\s*?|:\s+?) # separator
|
10
|
+
( # optional value begin
|
11
|
+
\s*'(?:\\'|[^'])*' # single quoted value
|
12
|
+
| # or
|
13
|
+
\s*"(?:\\"|[^"])*" # double quoted value
|
14
|
+
| # or
|
15
|
+
[^\#\r\n]+ # unquoted value
|
16
|
+
)? # value end
|
17
|
+
\s* # trailing whitespace
|
18
|
+
(?:\#.*)? # optional comment
|
19
|
+
(?:$|\z) # end of line
|
20
|
+
/x
|
21
|
+
|
22
|
+
Contract String => Hash
|
23
|
+
def call(string)
|
24
|
+
hash = {}
|
25
|
+
string.gsub(/\r\n?/, "\n").scan(LINE).each do |key, value|
|
26
|
+
hash[key] = parse_value(value || "")
|
27
|
+
end
|
28
|
+
hash
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def parse_value(value)
|
34
|
+
# Remove surrounding quotes
|
35
|
+
value = value.strip.sub(/\A(['"])(.*)\1\z/m, '\2')
|
36
|
+
|
37
|
+
if Regexp.last_match(1) == '"'
|
38
|
+
value = unescape_characters(expand_newlines(value))
|
39
|
+
end
|
40
|
+
|
41
|
+
value
|
42
|
+
end
|
43
|
+
|
44
|
+
def unescape_characters(value)
|
45
|
+
value.gsub(/\\([^$])/, '\1')
|
46
|
+
end
|
47
|
+
|
48
|
+
def expand_newlines(value)
|
49
|
+
value.gsub('\n', "\n").gsub('\r', "\r")
|
50
|
+
end
|
51
|
+
end
|