kuber_kit 0.1.7 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +4 -2
  3. data/README.md +16 -3
  4. data/TODO.md +4 -3
  5. data/example/configurations/review.rb +2 -1
  6. data/example/images/app_sources/Dockerfile +1 -1
  7. data/example/images/ruby_app/image.rb +4 -4
  8. data/example/infrastructure/build_servers.rb +8 -0
  9. data/example/services/env_file.rb +5 -1
  10. data/example/services/ruby_app.rb +2 -1
  11. data/kuber_kit.gemspec +1 -0
  12. data/lib/kuber_kit.rb +37 -19
  13. data/lib/kuber_kit/actions/configuration_loader.rb +11 -2
  14. data/lib/kuber_kit/actions/env_file_reader.rb +5 -0
  15. data/lib/kuber_kit/actions/image_compiler.rb +16 -10
  16. data/lib/kuber_kit/actions/kubectl_applier.rb +9 -3
  17. data/lib/kuber_kit/actions/kubectl_attacher.rb +26 -0
  18. data/lib/kuber_kit/actions/service_deployer.rb +34 -0
  19. data/lib/kuber_kit/actions/service_reader.rb +6 -0
  20. data/lib/kuber_kit/actions/template_reader.rb +5 -0
  21. data/lib/kuber_kit/cli.rb +54 -20
  22. data/lib/kuber_kit/configs.rb +24 -22
  23. data/lib/kuber_kit/container.rb +21 -13
  24. data/lib/kuber_kit/core/artifacts/artifact_store.rb +12 -23
  25. data/lib/kuber_kit/core/build_servers/abstract_build_server.rb +21 -0
  26. data/lib/kuber_kit/core/build_servers/build_server.rb +24 -0
  27. data/lib/kuber_kit/core/build_servers/build_server_store.rb +18 -0
  28. data/lib/kuber_kit/core/configuration.rb +10 -4
  29. data/lib/kuber_kit/core/configuration_definition.rb +18 -1
  30. data/lib/kuber_kit/core/configuration_factory.rb +11 -1
  31. data/lib/kuber_kit/core/configuration_store.rb +14 -24
  32. data/lib/kuber_kit/core/context_helper/service_helper.rb +2 -2
  33. data/lib/kuber_kit/core/env_files/env_file_store.rb +8 -23
  34. data/lib/kuber_kit/core/image_store.rb +8 -18
  35. data/lib/kuber_kit/core/registries/registry_store.rb +8 -23
  36. data/lib/kuber_kit/core/service.rb +6 -2
  37. data/lib/kuber_kit/core/service_store.rb +13 -23
  38. data/lib/kuber_kit/core/store.rb +48 -0
  39. data/lib/kuber_kit/core/templates/template_store.rb +12 -23
  40. data/lib/kuber_kit/image_compiler/build_server_pool.rb +31 -0
  41. data/lib/kuber_kit/image_compiler/build_server_pool_factory.rb +13 -0
  42. data/lib/kuber_kit/image_compiler/image_build_dir_creator.rb +13 -7
  43. data/lib/kuber_kit/image_compiler/image_dependency_resolver.rb +25 -5
  44. data/lib/kuber_kit/preprocessing/file_preprocessor.rb +5 -4
  45. data/lib/kuber_kit/service_deployer/strategies/kubernetes.rb +10 -3
  46. data/lib/kuber_kit/shell/abstract_shell.rb +4 -0
  47. data/lib/kuber_kit/shell/{bash_commands.rb → commands/bash_commands.rb} +1 -1
  48. data/lib/kuber_kit/shell/{docker_commands.rb → commands/docker_commands.rb} +1 -1
  49. data/lib/kuber_kit/shell/{git_commands.rb → commands/git_commands.rb} +1 -1
  50. data/lib/kuber_kit/shell/commands/kubectl_commands.rb +65 -0
  51. data/lib/kuber_kit/shell/commands/rsync_commands.rb +32 -0
  52. data/lib/kuber_kit/shell/local_shell.rb +24 -5
  53. data/lib/kuber_kit/shell/ssh_session.rb +62 -0
  54. data/lib/kuber_kit/shell/ssh_shell.rb +77 -0
  55. data/lib/kuber_kit/tools/file_presence_checker.rb +6 -2
  56. data/lib/kuber_kit/ui/interactive.rb +8 -0
  57. data/lib/kuber_kit/ui/simple.rb +6 -0
  58. data/lib/kuber_kit/version.rb +2 -2
  59. metadata +34 -12
  60. data/lib/kuber_kit/preprocessing/dir_preprocessor.rb +0 -19
  61. data/lib/kuber_kit/shell/kubectl_commands.rb +0 -42
  62. data/lib/kuber_kit/shell/rsync_commands.rb +0 -20
  63. data/lib/kuber_kit/tools/files_sync.rb +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7860f397b95796df7a9304a6fa169b31a3bd9e163e0e38def0c7d73c94dad95e
4
- data.tar.gz: 0ab17643bf762719394883b91cb08f5009d34e6ae9dbe823e27dd6f81b42f429
3
+ metadata.gz: 2164864d55b65ebdd1c62b766b16b3837ad7c3f676380a58b6f60b492b9eb0cd
4
+ data.tar.gz: 4517a27f92f73b1732bc7e7c200a0a6e037523fe07c6652f06f534a10266e0f8
5
5
  SHA512:
6
- metadata.gz: 5853d09c155988787409f6748280b4f65c57074d3d1dc6b2f5769231768596dadcc7cc811f3a68fd72db51984db031b15eaffe59e34fce3897177f2686aa389a
7
- data.tar.gz: 6871768abcf20b78b673db0f859f17d4b42835f6876b0bac4774ee854b4c6d702b51a574a404f91f06303c57967f584c4a83f8730f843918468e63e2d9b338b6
6
+ metadata.gz: 919f25e6aac48e750283df32a25a29a56e9c0111fefd7be084d9382478a79348a8072c381ee4f2a8bd95fc1f77ea3b7345904d1d260d4a1ee6820f131f453cd6
7
+ data.tar.gz: 441083ec69f68ad88e806c0e7ad95ad16a91547140f8649949187c088f778e1055c5e42c3b2813f9d4ff7557bacbdc65bb0ed3becdab36e5c7ffdc079d36eaea
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kuber_kit (0.1.7)
4
+ kuber_kit (0.2.2)
5
5
  cli-ui
6
6
  contracts-lite
7
7
  dry-auto_inject
8
+ net-ssh
8
9
  thor
9
10
 
10
11
  GEM
@@ -25,10 +26,11 @@ GEM
25
26
  dry-container (0.7.2)
26
27
  concurrent-ruby (~> 1.0)
27
28
  dry-configurable (~> 0.1, >= 0.1.3)
28
- dry-core (0.4.9)
29
+ dry-core (0.4.10)
29
30
  concurrent-ruby (~> 1.0)
30
31
  dry-equalizer (0.3.0)
31
32
  method_source (1.0.0)
33
+ net-ssh (6.1.0)
32
34
  pry (0.13.1)
33
35
  coderay (~> 1.1)
34
36
  method_source (~> 1.0)
data/README.md CHANGED
@@ -1,4 +1,8 @@
1
- # Docker Kit
1
+ # KuberKit
2
+
3
+ [![Codeship Status for ArtStation/kuber_kit](https://app.codeship.com/projects/1286f0a6-3f90-4c1b-b426-721ed8a6571b/status?branch=master)](https://app.codeship.com/projects/417264)
4
+
5
+ Solution for building & deploying applications on Kubernetes, written in Ruby.
2
6
 
3
7
  ## Installation
4
8
 
@@ -8,12 +12,21 @@ Add this line to your application's Gemfile:
8
12
  gem 'kuber_kit'
9
13
  ```
10
14
 
11
- ## Launch compilation for example images
15
+ ## Development
16
+
17
+ ### Launch compilation
18
+
19
+ ```
20
+ bin/kit compile ruby_app,ruby_app2 --path=./example
21
+ ```
22
+
23
+ ### Launch deployment
12
24
 
13
25
  ```
14
- bin/kit compile ruby_app,ruby_app2 --path=./example -C review
26
+ bin/kit compile -s ruby_app,ruby_app2 --path=./example
15
27
  ```
16
28
 
29
+
17
30
  ## License
18
31
 
19
32
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/TODO.md CHANGED
@@ -1,6 +1,7 @@
1
- - limit amount of simultaneous image builds
1
+ - allow setting default configuration for kuberkit using env variable
2
+ - implement interactive shell.exec!
3
+ - allow deploying only services enabled for specific configuration
2
4
  - list services and require confirmation before deployment
3
- - service factory should make sure that template exists
4
- - add build servers support
5
5
  - add build vars support (use images instead of containers)
6
+ - template should be able to set default attributes
6
7
  - template should be able to depend on image?
@@ -1,4 +1,5 @@
1
1
  KuberKit
2
2
  .define_configuration(:review)
3
3
  .use_registry(:review_default, as: :default)
4
- .use_artifact(:kuber_kit_repo, as: :kuber_kit_repo)
4
+ .use_artifact(:kuber_kit_repo, as: :kuber_kit_repo)
5
+ .use_build_server(:remote_bs)
@@ -1,4 +1,4 @@
1
- FROM default/ruby
1
+ FROM <%= image_url(:ruby) %>
2
2
 
3
3
  RUN mkdir -p /app
4
4
  WORKDIR /app
@@ -3,13 +3,13 @@ KuberKit
3
3
  .registry(:default)
4
4
  .depends_on(:ruby, :app_sources)
5
5
  .before_build do |context_helper, build_dir|
6
- # copy file local artifact
6
+ # copy file: local artifact
7
7
  source_path = context_helper.artifact_path(:kuber_kit_example_data, "test.txt")
8
8
  target_path = File.join(build_dir, "test.txt")
9
- context_helper.shell.exec!("cp #{source_path} #{target_path}")
9
+ context_helper.shell.sync(source_path, target_path)
10
10
 
11
- # copy file local artifact
11
+ # copy file: remote artifact
12
12
  source_path = context_helper.artifact_path(:kuber_kit_repo, "README.md")
13
13
  target_path = File.join(build_dir, "README.md")
14
- context_helper.shell.exec!("cp #{source_path} #{target_path}")
14
+ context_helper.shell.sync(source_path, target_path)
15
15
  end
@@ -0,0 +1,8 @@
1
+ ENV['SSH_TEST_HOST'] ||= "indocker.artstn.ninja"
2
+ ENV['SSH_TEST_USER'] ||= "kuber_kit"
3
+
4
+ KuberKit.add_build_server(
5
+ KuberKit::Core::BuildServers::BuildServer
6
+ .new(:remote_bs)
7
+ .setup(host: ENV['SSH_TEST_HOST'], user: ENV['SSH_TEST_USER'], port: 22)
8
+ )
@@ -1,3 +1,7 @@
1
1
  KuberKit
2
2
  .define_service(:env_file)
3
- .template(:env_file)
3
+ .template(:env_file)
4
+ .tags("env_file")
5
+ .attributes(
6
+ deployment_restart_enabled: false
7
+ )
@@ -1,4 +1,5 @@
1
1
  KuberKit
2
2
  .define_service(:ruby_app)
3
3
  .template(:service)
4
- .images(:ruby_app)
4
+ .images(:ruby_app)
5
+ .tags("app")
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.add_dependency "dry-auto_inject"
28
28
  spec.add_dependency "thor"
29
29
  spec.add_dependency "cli-ui"
30
+ spec.add_dependency "net-ssh"
30
31
 
31
32
  spec.add_development_dependency "bundler", "~> 1.17"
32
33
  spec.add_development_dependency "rake", "~> 10.0"
@@ -31,18 +31,7 @@ module KuberKit
31
31
  autoload :ConfigurationFactory, 'core/configuration_factory'
32
32
  autoload :Configuration, 'core/configuration'
33
33
 
34
- module ContextHelper
35
- autoload :BaseHelper, 'core/context_helper/base_helper'
36
- autoload :ImageHelper, 'core/context_helper/image_helper'
37
- autoload :ServiceHelper, 'core/context_helper/service_helper'
38
- autoload :ContextHelperFactory, 'core/context_helper/context_helper_factory'
39
- end
40
-
41
- module Registries
42
- autoload :AbstractRegistry, 'core/registries/abstract_registry'
43
- autoload :RegistryStore, 'core/registries/registry_store'
44
- autoload :Registry, 'core/registries/registry'
45
- end
34
+ autoload :Store, 'core/store'
46
35
 
47
36
  module Artifacts
48
37
  autoload :AbstractArtifact, 'core/artifacts/abstract_artifact'
@@ -51,12 +40,31 @@ module KuberKit
51
40
  autoload :Local, 'core/artifacts/local'
52
41
  end
53
42
 
43
+ module BuildServers
44
+ autoload :AbstractBuildServer, 'core/build_servers/abstract_build_server'
45
+ autoload :BuildServerStore, 'core/build_servers/build_server_store'
46
+ autoload :BuildServer, 'core/build_servers/build_server'
47
+ end
48
+
54
49
  module EnvFiles
55
50
  autoload :EnvFileStore, 'core/env_files/env_file_store'
56
51
  autoload :AbstractEnvFile, 'core/env_files/abstract_env_file'
57
52
  autoload :ArtifactFile, 'core/env_files/artifact_file'
58
53
  end
59
54
 
55
+ module ContextHelper
56
+ autoload :BaseHelper, 'core/context_helper/base_helper'
57
+ autoload :ImageHelper, 'core/context_helper/image_helper'
58
+ autoload :ServiceHelper, 'core/context_helper/service_helper'
59
+ autoload :ContextHelperFactory, 'core/context_helper/context_helper_factory'
60
+ end
61
+
62
+ module Registries
63
+ autoload :AbstractRegistry, 'core/registries/abstract_registry'
64
+ autoload :RegistryStore, 'core/registries/registry_store'
65
+ autoload :Registry, 'core/registries/registry'
66
+ end
67
+
60
68
  module Templates
61
69
  autoload :TemplateStore, 'core/templates/template_store'
62
70
  autoload :AbstractTemplate, 'core/templates/abstract_template'
@@ -67,22 +75,28 @@ module KuberKit
67
75
  module Tools
68
76
  autoload :FilePresenceChecker, 'tools/file_presence_checker'
69
77
  autoload :LoggerFactory, 'tools/logger_factory'
70
- autoload :FilesSync, 'tools/files_sync'
71
78
  end
72
79
 
73
80
  module Shell
74
81
  autoload :AbstractShell, 'shell/abstract_shell'
75
82
  autoload :LocalShell, 'shell/local_shell'
83
+ autoload :SshShell, 'shell/ssh_shell'
84
+ autoload :SshSession, 'shell/ssh_session'
76
85
  autoload :CommandCounter, 'shell/command_counter'
77
- autoload :BashCommands, 'shell/bash_commands'
78
- autoload :DockerCommands, 'shell/docker_commands'
79
- autoload :GitCommands, 'shell/git_commands'
80
- autoload :RsyncCommands, 'shell/rsync_commands'
81
- autoload :KubectlCommands, 'shell/kubectl_commands'
86
+
87
+ module Commands
88
+ autoload :BashCommands, 'shell/commands/bash_commands'
89
+ autoload :DockerCommands, 'shell/commands/docker_commands'
90
+ autoload :GitCommands, 'shell/commands/git_commands'
91
+ autoload :RsyncCommands, 'shell/commands/rsync_commands'
92
+ autoload :KubectlCommands, 'shell/commands/kubectl_commands'
93
+ end
82
94
  end
83
95
 
84
96
  module ImageCompiler
85
97
  autoload :ActionHandler, 'image_compiler/action_handler'
98
+ autoload :BuildServerPool, 'image_compiler/build_server_pool'
99
+ autoload :BuildServerPoolFactory, 'image_compiler/build_server_pool_factory'
86
100
  autoload :Compiler, 'image_compiler/compiler'
87
101
  autoload :ImageBuilder, 'image_compiler/image_builder'
88
102
  autoload :ImageBuildDirCreator, 'image_compiler/image_build_dir_creator'
@@ -93,7 +107,6 @@ module KuberKit
93
107
  module Preprocessing
94
108
  autoload :TextPreprocessor, 'preprocessing/text_preprocessor'
95
109
  autoload :FilePreprocessor, 'preprocessing/file_preprocessor'
96
- autoload :DirPreprocessor, 'preprocessing/dir_preprocessor'
97
110
  end
98
111
 
99
112
  module ArtifactsSync
@@ -144,6 +157,7 @@ module KuberKit
144
157
  autoload :ServiceDeployer, 'actions/service_deployer'
145
158
  autoload :ConfigurationLoader, 'actions/configuration_loader'
146
159
  autoload :KubectlApplier, 'actions/kubectl_applier'
160
+ autoload :KubectlAttacher, 'actions/kubectl_attacher'
147
161
  end
148
162
 
149
163
  module Extensions
@@ -212,6 +226,10 @@ module KuberKit
212
226
  Container["core.template_store"].add(template)
213
227
  end
214
228
 
229
+ def add_build_server(build_server)
230
+ Container["core.build_server_store"].add(build_server)
231
+ end
232
+
215
233
  def build_helper(&proc)
216
234
  KuberKit::Core::ContextHelper::BaseHelper.class_exec(&proc)
217
235
  end
@@ -50,6 +50,11 @@ class KuberKit::Actions::ConfigurationLoader
50
50
  files = service_store.load_definitions(services_path)
51
51
  task.update_title("Loaded #{files.count} service definitions")
52
52
  end
53
+
54
+ true
55
+ rescue KuberKit::Error => e
56
+ ui.print_error("Error", e.message)
57
+ false
53
58
  end
54
59
 
55
60
  def load_configurations(configurations_path, configuration_name)
@@ -60,13 +65,17 @@ class KuberKit::Actions::ConfigurationLoader
60
65
  configuration_name ||= :_default_
61
66
  end
62
67
 
68
+ all_configurations = configuration_store.all_definitions.values
63
69
  if configuration_store.count == 1 && configuration_name.nil?
64
- first_configurations = configuration_store.all_definitions.values.first
70
+ first_configurations = all_configurations.first
65
71
  configuration_name = first_configurations.configuration_name
66
72
  end
67
73
 
68
74
  if configuration_store.count > 1 && configuration_name.nil?
69
- raise KuberKit::Error, "Please set configuration name using -C option"
75
+ options = all_configurations.map(&:configuration_name).map(&:to_s)
76
+ ui.prompt("Please select configuration name (or set it using -C option)", options) do |selection|
77
+ configuration_name = selection
78
+ end
70
79
  end
71
80
 
72
81
  KuberKit.set_configuration_name(configuration_name)
@@ -11,5 +11,10 @@ class KuberKit::Actions::EnvFileReader
11
11
  def call(env_file_name, options)
12
12
  result = env_file_reader.call(local_shell, env_file_name)
13
13
  ui.print_info(env_file_name.to_s, JSON.pretty_generate(result))
14
+
15
+ true
16
+ rescue KuberKit::Error => e
17
+ ui.print_error("Error", e.message)
18
+ false
14
19
  end
15
20
  end
@@ -1,6 +1,7 @@
1
1
  class KuberKit::Actions::ImageCompiler
2
2
  include KuberKit::Import[
3
3
  "image_compiler.image_dependency_resolver",
4
+ "image_compiler.build_server_pool_factory",
4
5
  "shell.local_shell",
5
6
  "tools.logger",
6
7
  "ui",
@@ -10,27 +11,32 @@ class KuberKit::Actions::ImageCompiler
10
11
  Contract ArrayOf[Symbol], Hash => Any
11
12
  def call(image_names, options)
12
13
  build_id = generate_build_id
14
+ build_server_pool = build_server_pool_factory.create()
13
15
 
14
- resolved_dependencies = []
15
- dependencies = image_dependency_resolver.get_next(image_names)
16
-
17
- while (dependencies - resolved_dependencies).any?
18
- compile_simultaneously(dependencies, build_id)
19
- resolved_dependencies += dependencies
20
- dependencies = image_dependency_resolver.get_next(image_names, resolved: resolved_dependencies)
16
+ image_dependency_resolver.each_with_deps(image_names) do |dep_image_names|
17
+ result = compile_simultaneously(dep_image_names, build_id, build_server_pool)
18
+ abort unless result
21
19
  end
22
20
 
23
- compile_simultaneously(image_names - resolved_dependencies, build_id)
21
+ build_server_pool.disconnect_all
22
+
23
+ true
24
+ rescue KuberKit::Error => e
25
+ ui.print_error("Error", e.message)
26
+
27
+ false
24
28
  end
25
29
 
26
30
  private
27
- def compile_simultaneously(image_names, build_id)
31
+ def compile_simultaneously(image_names, build_id, build_server_pool)
28
32
  task_group = ui.create_task_group
29
33
  image_names.map do |image_name|
30
34
 
31
35
  logger.info("Started compiling: #{image_name.to_s.green}")
32
36
  task_group.add("Compiling #{image_name.to_s.yellow}") do |task|
33
- image_compiler.call(local_shell, image_name, build_id)
37
+ shell = build_server_pool.get_shell
38
+
39
+ image_compiler.call(shell, image_name, build_id)
34
40
 
35
41
  task.update_title("Compiled #{image_name.to_s.green}")
36
42
  logger.info("Finished compiling: #{image_name.to_s.green}")
@@ -7,11 +7,17 @@ class KuberKit::Actions::KubectlApplier
7
7
 
8
8
  Contract String, Hash => Any
9
9
  def call(file_path, options)
10
- kubeconfig_path = KuberKit.current_configuration.kubeconfig_path
10
+ kubeconfig_path = KuberKit.current_configuration.kubeconfig_path
11
+ deploy_namespace = KuberKit.current_configuration.deploy_namespace
11
12
  ui.create_task("Applying file: #{file_path}") do |task|
12
- kubectl_commands.apply_file(local_shell, file_path, kubeconfig_path: kubeconfig_path)
13
+ kubectl_commands.apply_file(local_shell, file_path, kubeconfig_path: kubeconfig_path, namespace: deploy_namespace)
13
14
  task.update_title("Applied file: #{file_path}")
14
15
  end
15
- nil
16
+
17
+ true
18
+ rescue KuberKit::Error => e
19
+ ui.print_error("Error", e.message)
20
+
21
+ false
16
22
  end
17
23
  end
@@ -0,0 +1,26 @@
1
+ class KuberKit::Actions::KubectlAttacher
2
+ include KuberKit::Import[
3
+ "shell.kubectl_commands",
4
+ "shell.local_shell",
5
+ "ui"
6
+ ]
7
+
8
+ Contract String, Hash => Any
9
+ def call(pod_name, options)
10
+ kubeconfig_path = KuberKit.current_configuration.kubeconfig_path
11
+ deploy_namespace = KuberKit.current_configuration.deploy_namespace
12
+
13
+ kubectl_commands.exec(
14
+ local_shell, pod_name, "bash", args: "-it",
15
+ kubeconfig_path: kubeconfig_path,
16
+ interactive: true,
17
+ namespace: deploy_namespace
18
+ )
19
+
20
+ true
21
+ rescue KuberKit::Error => e
22
+ ui.print_error("Error", e.message)
23
+
24
+ false
25
+ end
26
+ end
@@ -14,6 +14,10 @@ class KuberKit::Actions::ServiceDeployer
14
14
  tags: Maybe[ArrayOf[String]],
15
15
  ] => Any
16
16
  def call(services:, tags:)
17
+ if services.empty? && tags.empty?
18
+ services, tags = show_tags_selection
19
+ end
20
+
17
21
  service_names = service_list_resolver.resolve(
18
22
  services: services || [],
19
23
  tags: tags || []
@@ -31,6 +35,12 @@ class KuberKit::Actions::ServiceDeployer
31
35
 
32
36
  compile_images(images_names)
33
37
  deploy_services(service_names)
38
+
39
+ true
40
+ rescue KuberKit::Error => e
41
+ ui.print_error("Error", e.message)
42
+
43
+ false
34
44
  end
35
45
 
36
46
  def deploy_services(service_names)
@@ -53,4 +63,28 @@ class KuberKit::Actions::ServiceDeployer
53
63
  def compile_images(images_names)
54
64
  image_compiler.call(images_names, {}) if images_names.any?
55
65
  end
66
+
67
+ def show_tags_selection()
68
+ specific_service_option = "deploy specific service"
69
+
70
+ tags = service_store.all_definitions.values.map(&:to_service_attrs).map(&:tags).flatten.uniq.map(&:to_s)
71
+
72
+ tags.push(specific_service_option)
73
+
74
+ ui.prompt("Please select which tag to deploy", tags) do |selected_tag|
75
+ if selected_tag == specific_service_option
76
+ show_service_selection
77
+ else
78
+ return [[], [selected_tag]]
79
+ end
80
+ end
81
+ end
82
+
83
+ def show_service_selection()
84
+ services = service_store.all_definitions.values.map(&:service_name).uniq.map(&:to_s)
85
+
86
+ ui.prompt("Please select which service to deploy", services) do |selected_service|
87
+ return [[selected_service], []]
88
+ end
89
+ end
56
90
  end