uffizzi-cli 0.3.7 → 0.5.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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -0
  3. data/config/uffizzi.rb +1 -0
  4. data/lib/uffizzi/cli/common.rb +2 -2
  5. data/lib/uffizzi/cli/config.rb +3 -3
  6. data/lib/uffizzi/cli/connect.rb +22 -0
  7. data/lib/uffizzi/cli/disconnect.rb +46 -0
  8. data/lib/uffizzi/cli/logout.rb +4 -0
  9. data/lib/uffizzi/cli/preview/service.rb +40 -3
  10. data/lib/uffizzi/cli/preview.rb +38 -34
  11. data/lib/uffizzi/cli/project/compose.rb +2 -2
  12. data/lib/uffizzi/cli/project/secret.rb +7 -6
  13. data/lib/uffizzi/cli.rb +37 -8
  14. data/lib/uffizzi/clients/api/api_client.rb +14 -0
  15. data/lib/uffizzi/clients/api/api_routes.rb +8 -0
  16. data/lib/uffizzi/error.rb +5 -0
  17. data/lib/uffizzi/shell.rb +27 -2
  18. data/lib/uffizzi/version.rb +1 -1
  19. data/lib/uffizzi.rb +2 -2
  20. data/man/uffizzi +51 -0
  21. data/man/uffizzi-login +32 -0
  22. data/man/uffizzi-login.html +113 -0
  23. data/man/uffizzi-login.ronn +24 -0
  24. data/man/uffizzi-logout +1 -1
  25. data/man/uffizzi-logout.html +102 -0
  26. data/man/uffizzi-preview +2 -2
  27. data/man/{uffizzi-create → uffizzi-preview-create} +2 -2
  28. data/man/uffizzi-preview-create.html +128 -0
  29. data/man/{uffizzi-create.ronn → uffizzi-preview-create.ronn} +1 -1
  30. data/man/{uffizzi-delete → uffizzi-preview-delete} +2 -2
  31. data/man/uffizzi-preview-delete.html +115 -0
  32. data/man/{uffizzi-delete.ronn → uffizzi-preview-delete.ronn} +1 -1
  33. data/man/{uffizzi-describe → uffizzi-preview-describe} +2 -2
  34. data/man/uffizzi-preview-describe.html +116 -0
  35. data/man/{uffizzi-describe.ronn → uffizzi-preview-describe.ronn} +1 -1
  36. data/man/{uffizzi-events → uffizzi-preview-events} +22 -15
  37. data/man/uffizzi-preview-events.html +110 -0
  38. data/man/{uffizzi-events.ronn → uffizzi-preview-events.ronn} +7 -8
  39. data/man/{uffizzi-list → uffizzi-preview-list} +2 -2
  40. data/man/uffizzi-preview-list.html +110 -0
  41. data/man/{uffizzi-list.ronn → uffizzi-preview-list.ronn} +1 -1
  42. data/man/uffizzi-preview-service-list +38 -0
  43. data/man/uffizzi-preview-service-list.ronn +29 -0
  44. data/man/uffizzi-preview-service-logs +57 -0
  45. data/man/uffizzi-preview-service-logs.ronn +47 -0
  46. data/man/uffizzi-preview.html +120 -0
  47. data/man/uffizzi-preview.ronn +1 -1
  48. data/man/uffizzi-preview_service_logs +57 -0
  49. data/man/uffizzi-preview_service_logs.html +142 -0
  50. data/man/uffizzi-preview_service_logs.ronn +49 -0
  51. data/man/uffizzi-project +47 -0
  52. data/man/uffizzi-project-compose +40 -0
  53. data/man/uffizzi-project-compose-describe +37 -0
  54. data/man/uffizzi-project-compose-describe.html +118 -0
  55. data/man/uffizzi-project-compose-describe.ronn +29 -0
  56. data/man/uffizzi-project-compose-set +66 -0
  57. data/man/uffizzi-project-compose-set.html +149 -0
  58. data/man/uffizzi-project-compose-set.ronn +57 -0
  59. data/man/uffizzi-project-compose-unset +35 -0
  60. data/man/uffizzi-project-compose-unset.html +116 -0
  61. data/man/uffizzi-project-compose-unset.ronn +27 -0
  62. data/man/uffizzi-project-compose.html +123 -0
  63. data/man/uffizzi-project-compose.ronn +34 -0
  64. data/man/uffizzi-project-secret +37 -0
  65. data/man/uffizzi-project-secret-create +29 -0
  66. data/man/uffizzi-project-secret-create.html +110 -0
  67. data/man/uffizzi-project-secret-create.ronn +21 -0
  68. data/man/uffizzi-project-secret-delete +29 -0
  69. data/man/uffizzi-project-secret-delete.html +110 -0
  70. data/man/uffizzi-project-secret-delete.ronn +21 -0
  71. data/man/uffizzi-project-secret-list +28 -0
  72. data/man/uffizzi-project-secret-list.html +110 -0
  73. data/man/uffizzi-project-secret-list.ronn +20 -0
  74. data/man/uffizzi-project-secret.html +119 -0
  75. data/man/uffizzi-project-secret.ronn +30 -0
  76. data/man/uffizzi-project.html +128 -0
  77. data/man/uffizzi-project.ronn +41 -0
  78. data/man/uffizzi.html +132 -0
  79. data/man/uffizzi.ronn +43 -0
  80. metadata +89 -54
  81. data/.dockerignore +0 -9
  82. data/.rubocop.yml +0 -578
  83. data/CHANGELOG.md +0 -5
  84. data/CONTRIBUTING.md +0 -13
  85. data/Dockerfile +0 -46
  86. data/Gemfile +0 -5
  87. data/Gemfile.lock +0 -122
  88. data/Makefile +0 -31
  89. data/Rakefile +0 -21
  90. data/bin/console +0 -15
  91. data/bin/setup +0 -8
  92. data/docker-compose.yml +0 -29
  93. data/docker-entrypoint.sh +0 -20
  94. data/uffizzi.gemspec +0 -50
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f4c103c385742d901959f98e01af795e472acae632cc162d74632be49b585fa
4
- data.tar.gz: b80618d6497a312b3b32605ae3778fcfce39e3aab4fad248daf8f3c7e52ff8cf
3
+ metadata.gz: beaa38102ec282e48c643ba8f6a8c80a331d6ded1760681a004341e2b671b5cf
4
+ data.tar.gz: c6517ea90506e72c11cb244f02f00760d5bb2afa1171f48fc9a997a8489165f0
5
5
  SHA512:
6
- metadata.gz: 00e878c19604b0a70668fc4eaacd46fdcc2c5bd63a8ff3c9ab0947bd7a3600e84968d09cc862d0e7257a1ab019c0eb8ec3ee5b5202a4f0ba6d9c03dbaa226c60
7
- data.tar.gz: 1d3613c7c3f4a613cc1e719243747e79d7b78e3941fe2f2da5b1a5e0a6a1d9a3aa5d96ce70a20925f236e3f3dc541ef82c17bd80fb04ee3153892a75e68097b5
6
+ metadata.gz: 2736a387fb65e9efe83fda0311f9f79bf4916bc828e9b6113bbf7e4e407256438e607af8f1f46dc6df1fa43423ba4728f6432396b60e06c24e16270024382f7a
7
+ data.tar.gz: 53b0f5951c72ebfba472e147e4397d311380b051baf41d3ca2c7e20f894a3ea417406f4ac8fbc3063902a79c7e11f1e39d5246aee0505377b01583d733056914
data/README.md CHANGED
@@ -176,6 +176,20 @@ $ uffizzi config delete OPTION
176
176
 
177
177
  Deletes specified option.
178
178
 
179
+ ### disconnect ###
180
+
181
+ ```
182
+ $ uffizzi disconnect CREDENTIAL_TYPE
183
+ ```
184
+
185
+ Deletes credential of specified type
186
+
187
+ Supported credential types - `docker-hub`, `acr`, `ecr`, `gcr`
188
+
189
+ ## Generate manual
190
+
191
+ In order to generate a manual, create a `.ronn` file having a name pattern like `uffizzi-{command-name}` (for example `uffizzi-project-compose`) in the `man` directory and run `bundle exec ronn man/{filename}.ronn`
192
+
179
193
  ## Git workflow for the app:
180
194
 
181
195
  1. Clone the repository and checkout to `develop` branch
data/config/uffizzi.rb CHANGED
@@ -18,6 +18,7 @@ module Uffizzi
18
18
  azure: 'UffizziCore::Credential::Azure',
19
19
  google: 'UffizziCore::Credential::Google',
20
20
  amazon: 'UffizziCore::Credential::Amazon',
21
+ github_container_registry: 'UffizziCore::Credential::GithubContainerRegistry',
21
22
  }
22
23
  end
23
24
  end
@@ -5,8 +5,8 @@ require 'open3'
5
5
  module Cli
6
6
  class Common
7
7
  class << self
8
- def show_manual(method_name)
9
- manual_doc_path = "man/uffizzi-#{method_name}"
8
+ def show_manual(command_name)
9
+ manual_doc_path = "man/#{command_name}"
10
10
 
11
11
  Open3.pipeline("man #{manual_doc_path}")
12
12
  end
@@ -12,17 +12,17 @@ module Uffizzi
12
12
  run('list')
13
13
  end
14
14
 
15
- desc 'get', 'get'
15
+ desc 'get [PROPERTY]', 'get'
16
16
  def get(property)
17
17
  run('get', property)
18
18
  end
19
19
 
20
- desc 'set', 'set'
20
+ desc 'set [PROPERTY] [VALUE]', 'set'
21
21
  def set(property, value)
22
22
  run('set', property, value)
23
23
  end
24
24
 
25
- desc 'delete', 'delete'
25
+ desc 'delete [PROPERTY]', 'delete'
26
26
  def delete(property)
27
27
  run('delete', property)
28
28
  end
@@ -14,6 +14,8 @@ module Uffizzi
14
14
  handle_azure
15
15
  when 'ecr'
16
16
  handle_amazon
17
+ when 'ghcr'
18
+ handle_github_container_registry
17
19
  when 'gcr'
18
20
  handle_google(credential_file_path)
19
21
  else
@@ -111,6 +113,26 @@ module Uffizzi
111
113
  end
112
114
  end
113
115
 
116
+ def handle_github_container_registry
117
+ username = Uffizzi.ui.ask('Github Username: ')
118
+ password = Uffizzi.ui.ask('Access Token: ', echo: false)
119
+
120
+ params = {
121
+ username: username,
122
+ password: password,
123
+ type: Uffizzi.configuration.credential_types[:github_container_registry],
124
+ }
125
+
126
+ hostname = ConfigFile.read_option(:hostname)
127
+ response = create_credential(hostname, params)
128
+
129
+ if ResponseHelper.created?(response)
130
+ print_success_message('GitHub Container Registry')
131
+ else
132
+ ResponseHelper.handle_failed_response(response)
133
+ end
134
+ end
135
+
114
136
  def prepare_registry_url(registry_url)
115
137
  return registry_url if registry_url.match?(/^(?:http(s)?:\/\/)/)
116
138
 
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uffizzi'
4
+
5
+ module Uffizzi
6
+ class CLI::Disconnect
7
+ include ApiClient
8
+
9
+ def run(credential_type)
10
+ connection_type = case credential_type
11
+ when 'docker-hub'
12
+ Uffizzi.configuration.credential_types[:dockerhub]
13
+ when 'acr'
14
+ Uffizzi.configuration.credential_types[:azure]
15
+ when 'ecr'
16
+ Uffizzi.configuration.credential_types[:amazon]
17
+ when 'gcr'
18
+ Uffizzi.configuration.credential_types[:google]
19
+ when 'ghcr'
20
+ Uffizzi.configuration.credential_types[:github_container_registry]
21
+ else
22
+ raise Uffizzi::Error.new('Unsupported credential type.')
23
+ end
24
+
25
+ response = delete_credential(ConfigFile.read_option(:hostname), connection_type)
26
+
27
+ if ResponseHelper.no_content?(response)
28
+ Uffizzi.ui.say("Successfully disconnected #{connection_name(credential_type)} connection")
29
+ else
30
+ ResponseHelper.handle_failed_response(response)
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def connection_name(credential_type)
37
+ {
38
+ 'docker-hub' => 'DockerHub',
39
+ 'acr' => 'ACR',
40
+ 'ecr' => 'ECR',
41
+ 'gcr' => 'GCR',
42
+ 'ghcr' => 'GHCR',
43
+ }[credential_type]
44
+ end
45
+ end
46
+ end
@@ -7,6 +7,10 @@ module Uffizzi
7
7
  class CLI::Logout
8
8
  include ApiClient
9
9
 
10
+ def initialize(options)
11
+ @options = options
12
+ end
13
+
10
14
  def run
11
15
  return Uffizzi.ui.say('You are not logged in') unless Uffizzi::AuthHelper.signed_in?
12
16
 
@@ -9,7 +9,23 @@ module Uffizzi
9
9
  class CLI::Preview::Service < Thor
10
10
  include ApiClient
11
11
 
12
- desc 'list', 'list'
12
+ desc 'logs [LOGS_TYPE] [DEPLOYMENT_ID] [CONTAINER_NAME]', 'logs'
13
+ def logs(logs_type, deployment_name, container_name = args)
14
+ return Uffizzi.ui.say('You are not logged in.') unless Uffizzi::AuthHelper.signed_in?
15
+ return Uffizzi.ui.say('This command needs project to be set in config file') unless Uffizzi::AuthHelper.project_set?
16
+
17
+ deployment_id = PreviewService.read_deployment_id(deployment_name)
18
+ response = service_logs_response(logs_type, deployment_id, container_name)
19
+ return Uffizzi.ui.say(response[:errors]) if response[:errors]
20
+
21
+ if ResponseHelper.ok?(response)
22
+ handle_succeed_logs_response(response, container_name)
23
+ else
24
+ ResponseHelper.handle_failed_response(response)
25
+ end
26
+ end
27
+
28
+ desc 'logs [DEPLOYMENT_ID]', 'list'
13
29
  def list(deployment_name)
14
30
  return Uffizzi.ui.say('You are not logged in.') unless Uffizzi::AuthHelper.signed_in?
15
31
  return Uffizzi.ui.say('This command needs project to be set in config file') unless Uffizzi::AuthHelper.project_set?
@@ -20,7 +36,7 @@ module Uffizzi
20
36
  response = fetch_deployment_services(hostname, project_slug, deployment_id)
21
37
 
22
38
  if ResponseHelper.ok?(response)
23
- handle_succeed_response(response, deployment_name)
39
+ handle_succeed_list_response(response, deployment_name)
24
40
  else
25
41
  ResponseHelper.handle_failed_response(response)
26
42
  end
@@ -28,7 +44,19 @@ module Uffizzi
28
44
 
29
45
  private
30
46
 
31
- def handle_succeed_response(response, deployment_name)
47
+ def service_logs_response(logs_type, deployment_id, container_name)
48
+ project_slug = ConfigFile.read_option(:project)
49
+ hostname = ConfigFile.read_option(:hostname)
50
+
51
+ case logs_type
52
+ when 'container'
53
+ fetch_deployment_service_logs(hostname, project_slug, deployment_id, container_name)
54
+ else
55
+ raise Uffizzi::Error.new('Unknown log type')
56
+ end
57
+ end
58
+
59
+ def handle_succeed_list_response(response, deployment_name)
32
60
  services = response[:body][:containers] || []
33
61
  return Uffizzi.ui.say("There are no services associated with the preview #{deployment_name}") if services.empty?
34
62
 
@@ -36,5 +64,14 @@ module Uffizzi
36
64
  Uffizzi.ui.say(service)
37
65
  end
38
66
  end
67
+
68
+ def handle_succeed_logs_response(response, container_name)
69
+ logs = response[:body][:logs] || []
70
+ return Uffizzi.ui.say("The service #{container_name} has no logs") if logs.empty?
71
+
72
+ logs.each do |log|
73
+ Uffizzi.ui.say(log)
74
+ end
75
+ end
39
76
  end
40
77
  end
@@ -10,56 +10,45 @@ module Uffizzi
10
10
 
11
11
  @spinner
12
12
 
13
- class << self
14
- def help(_shell, _subcommand)
15
- Cli::Common.show_manual(:preview)
16
- end
17
- end
18
-
19
13
  desc 'service', 'service'
20
14
  require_relative 'preview/service'
21
15
  subcommand 'service', Uffizzi::CLI::Preview::Service
22
16
 
23
17
  desc 'list', 'list'
24
18
  def list
25
- return Cli::Common.show_manual(:list) if options[:help]
26
-
27
- run(options, 'list')
19
+ run('list')
28
20
  end
29
21
 
30
- desc 'create', 'create'
22
+ desc 'create [COMPOSE_FILE]', 'create'
23
+ method_option :output, required: false, type: :string, aliases: '-o', enum: ['json', 'github-action']
31
24
  def create(file_path = nil)
32
- return Cli::Common.show_manual(:create) if options[:help]
33
-
34
- run(options, 'create', file_path: file_path)
25
+ run('create', file_path: file_path)
35
26
  end
36
27
 
37
- desc 'delete', 'delete'
28
+ desc 'delete [DEPLOYMENT_ID]', 'delete'
38
29
  def delete(deployment_name)
39
- return Cli::Common.show_manual(:delete) if options[:help]
40
-
41
- run(options, 'delete', deployment_name: deployment_name)
30
+ run('delete', deployment_name: deployment_name)
42
31
  end
43
32
 
44
- desc 'describe', 'describe'
33
+ desc 'describe [DEPLOYMENT_ID]', 'describe'
45
34
  def describe(deployment_name)
46
- return Cli::Common.show_manual(:describe) if options[:help]
47
-
48
- run(options, 'describe', deployment_name: deployment_name)
35
+ run('describe', deployment_name: deployment_name)
49
36
  end
50
37
 
51
- desc 'events', 'events'
38
+ desc 'events [DEPLOYMENT_ID]', 'events'
52
39
  def events(deployment_name)
53
- return Cli::Common.show_manual(:events) if options[:help]
54
-
55
- run(options, 'events', deployment_name: deployment_name)
40
+ run('events', deployment_name: deployment_name)
56
41
  end
57
42
 
58
43
  private
59
44
 
60
- def run(options, command, file_path: nil, deployment_name: nil)
61
- return Uffizzi.ui.say('You are not logged in.') unless Uffizzi::AuthHelper.signed_in?
62
- return Uffizzi.ui.say('This command needs project to be set in config file') unless Uffizzi::AuthHelper.project_set?
45
+ def run(command, file_path: nil, deployment_name: nil)
46
+ unless options[:output].nil?
47
+ Uffizzi.ui.output_format = options[:output]
48
+ Uffizzi.ui.disable_stdout
49
+ end
50
+ raise Uffizzi::Error.new('You are not logged in.') unless Uffizzi::AuthHelper.signed_in?
51
+ raise Uffizzi::Error.new('This command needs project to be set in config file') unless Uffizzi::AuthHelper.project_set?
63
52
 
64
53
  project_slug = options[:project].nil? ? ConfigFile.read_option(:project) : options[:project]
65
54
 
@@ -161,6 +150,19 @@ module Uffizzi
161
150
 
162
151
  containers_spinners = create_containers_spinners(activity_items)
163
152
 
153
+ wait_containers_deploying(project_slug, deployment_id, containers_spinners)
154
+
155
+ if options[:output].nil?
156
+ Uffizzi.ui.say('Done')
157
+ preview_url = "https://#{deployment[:preview_url]}"
158
+ Uffizzi.ui.say(preview_url) if @spinner.success?
159
+ else
160
+ output_data = build_output_data(deployment)
161
+ Uffizzi.ui.output(output_data)
162
+ end
163
+ end
164
+
165
+ def wait_containers_deploying(project_slug, deployment_id, containers_spinners)
164
166
  loop do
165
167
  response = get_activity_items(ConfigFile.read_option(:hostname), project_slug, deployment_id)
166
168
  handle_activity_items_response(response)
@@ -172,10 +174,6 @@ module Uffizzi
172
174
 
173
175
  sleep(5)
174
176
  end
175
-
176
- Uffizzi.ui.say('Done')
177
- preview_url = "http://#{deployment[:preview_url]}"
178
- Uffizzi.ui.say(preview_url) if @spinner.success?
179
177
  end
180
178
 
181
179
  def create_containers_spinners(activity_items)
@@ -264,8 +262,7 @@ module Uffizzi
264
262
  begin
265
263
  compose_file_data = File.read(file_path)
266
264
  rescue Errno::ENOENT => e
267
- Uffizzi.ui.say(e)
268
- return
265
+ raise Uffizzi::Error.new(e.message)
269
266
  end
270
267
 
271
268
  compose_file_dir = File.dirname(file_path)
@@ -282,5 +279,12 @@ module Uffizzi
282
279
  dependencies: dependencies,
283
280
  }
284
281
  end
282
+
283
+ def build_output_data(output_data)
284
+ {
285
+ id: "deployment-#{output_data[:id]}",
286
+ url: "https://#{output_data[:preview_url]}",
287
+ }
288
+ end
285
289
  end
286
290
  end
@@ -10,7 +10,7 @@ module Uffizzi
10
10
  class CLI::Project::Compose < Thor
11
11
  include ApiClient
12
12
 
13
- desc 'set', 'set'
13
+ desc 'set [OPTIONS]', 'set'
14
14
  def set
15
15
  run(options, 'set')
16
16
  end
@@ -96,7 +96,7 @@ module Uffizzi
96
96
  begin
97
97
  compose_file_data = EnvVariablesService.substitute_env_variables(File.read(file_path))
98
98
  rescue Errno::ENOENT => e
99
- return Uffizzi.ui.say(e)
99
+ raise Uffizzi::Error.new(e.message)
100
100
  end
101
101
 
102
102
  compose_file_dir = File.dirname(file_path)
@@ -14,19 +14,20 @@ module Uffizzi
14
14
  run('list')
15
15
  end
16
16
 
17
- desc 'create', 'Create secrets'
17
+ desc 'create [SECRET_ID]', 'Create secrets from $stdout'
18
18
  def create(id)
19
19
  run('create', id)
20
20
  end
21
21
 
22
- desc 'delete', 'Delete a secret'
22
+ desc 'delete [SECRET_ID]', 'Delete a secret'
23
23
  def delete(id)
24
24
  run('delete', id)
25
25
  end
26
26
 
27
27
  private
28
28
 
29
- def run(command, args = {})
29
+ def run(command, id = nil)
30
+ Cli::Common.show_manual(:project, :secret, command) if options[:help] || args.include?('help')
30
31
  return Uffizzi.ui.say('You are not logged in') unless AuthHelper.signed_in?
31
32
 
32
33
  project_slug = ConfigFile.read_option(:project)
@@ -36,13 +37,13 @@ module Uffizzi
36
37
  when 'list'
37
38
  handle_list_command(project_slug)
38
39
  when 'create'
39
- handle_create_command(project_slug, args)
40
+ handle_create_command(project_slug, id)
40
41
  when 'delete'
41
- handle_delete_command(project_slug, args)
42
+ handle_delete_command(project_slug, id)
42
43
  else
43
44
  error_message = "The subcommand #{command} does not exist, please run 'uffizzi project secret help' \
44
45
  to get the list of available subcommands"
45
- Uffizzi.ui.say(error_message)
46
+ raise Thor::Error.new(error_message)
46
47
  end
47
48
  end
48
49
 
data/lib/uffizzi/cli.rb CHANGED
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'thor'
4
3
  require 'uffizzi'
5
4
 
6
5
  module Uffizzi
7
6
  class CLI < Thor
8
- require_relative 'cli/common'
9
- class_option :help, type: :boolean, aliases: ['-h', 'help']
7
+ def self.exit_on_failure?
8
+ true
9
+ end
10
10
 
11
11
  desc 'version', 'show version'
12
12
  def version
@@ -14,7 +14,7 @@ module Uffizzi
14
14
  Uffizzi.ui.say(Uffizzi::VERSION)
15
15
  end
16
16
 
17
- desc 'login', 'Login into Uffizzi'
17
+ desc 'login [OPTIONS]', 'Login into Uffizzi'
18
18
  method_option :user, required: true, aliases: '-u'
19
19
  method_option :hostname, required: true
20
20
  def login
@@ -23,11 +23,9 @@ module Uffizzi
23
23
  end
24
24
 
25
25
  desc 'logout', 'Logout from Uffizzi'
26
- def logout(help = nil)
27
- return Cli::Common.show_manual(:logout) if help || options[:help]
28
-
26
+ def logout
29
27
  require_relative 'cli/logout'
30
- Logout.new.run
28
+ Logout.new(options).run
31
29
  end
32
30
 
33
31
  desc 'projects', 'projects'
@@ -54,5 +52,36 @@ module Uffizzi
54
52
  require_relative 'cli/connect'
55
53
  Connect.new.run(credential_type, credential_file_path)
56
54
  end
55
+
56
+ desc 'disconect CREDENTIAL_TYPE', 'Disonnect credentials from Uffizzi'
57
+ def disconnect(credential_type)
58
+ require_relative 'cli/disconnect'
59
+ Disconnect.new.run(credential_type)
60
+ end
61
+
62
+ class << self
63
+ protected
64
+
65
+ def dispatch(meth, given_args, given_opts, config)
66
+ args, opts = Thor::Options.split(given_args)
67
+ return Cli::Common.show_manual(filename(args)) if show_help?(args, opts)
68
+
69
+ super
70
+ end
71
+
72
+ private
73
+
74
+ def filename(args)
75
+ args_without_help = args.reject { |arg| arg == 'help' }
76
+ return 'uffizzi' if args_without_help.empty?
77
+
78
+ "uffizzi-#{args_without_help.join('-')}"
79
+ end
80
+
81
+ def show_help?(args, opts)
82
+ help_options = ['--help', '-h', '--help=true']
83
+ args.empty? || args.include?('help') || opts.any? { |opt| help_options.include?(opt) }
84
+ end
85
+ end
57
86
  end
58
87
  end
@@ -41,6 +41,20 @@ module ApiClient
41
41
  build_response(response)
42
42
  end
43
43
 
44
+ def delete_credential(hostname, credential_type)
45
+ uri = delete_credential_uri(hostname, credential_type)
46
+ response = Uffizzi::HttpClient.make_delete_request(uri)
47
+
48
+ build_response(response)
49
+ end
50
+
51
+ def fetch_deployment_service_logs(hostname, project_slug, deployment_id, container_name)
52
+ uri = preview_service_logs_uri(hostname, project_slug, deployment_id, container_name)
53
+ response = Uffizzi::HttpClient.make_get_request(uri)
54
+
55
+ build_response(response)
56
+ end
57
+
44
58
  def set_compose_file(hostname, params, project_slug)
45
59
  uri = compose_file_uri(hostname, project_slug)
46
60
  response = Uffizzi::HttpClient.make_post_request(uri, params)
@@ -55,4 +55,12 @@ module ApiRoutes
55
55
  def preview_services_uri(hostname, project_slug, deployment_id)
56
56
  "#{hostname}/api/cli/v1/projects/#{project_slug}/deployments/#{deployment_id}/containers"
57
57
  end
58
+
59
+ def delete_credential_uri(hostname, credential_type)
60
+ "#{hostname}/api/cli/v1/account/credentials/#{credential_type}"
61
+ end
62
+
63
+ def preview_service_logs_uri(hostname, project_slug, deployment_id, container_name)
64
+ "#{hostname}/api/cli/v1/projects/#{project_slug}/deployments/#{deployment_id}/containers/#{container_name}/logs"
65
+ end
58
66
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Uffizzi
4
+ class Error < Thor::Error; end
5
+ end
data/lib/uffizzi/shell.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'thor'
4
-
5
3
  module Uffizzi
6
4
  module UI
7
5
  class Shell
6
+ attr_accessor :output_format
7
+
8
8
  def initialize
9
9
  @shell = Thor::Shell::Basic.new
10
10
  end
@@ -28,6 +28,31 @@ module Uffizzi
28
28
  def last_message
29
29
  @shell.send(:stdout).string.strip
30
30
  end
31
+
32
+ def disable_stdout
33
+ $stdout = StringIO.new
34
+ end
35
+
36
+ def output(data)
37
+ $stdout = IO.new(1, 'w')
38
+ json_format? ? output_in_json(data) : output_in_github_format(data)
39
+ end
40
+
41
+ private
42
+
43
+ def json_format?
44
+ output_format == 'json'
45
+ end
46
+
47
+ def output_in_json(data)
48
+ say(data.to_json)
49
+ end
50
+
51
+ def output_in_github_format(data)
52
+ data.each_key do |key|
53
+ say("::set-output name=#{key}::#{data[key]}")
54
+ end
55
+ end
31
56
  end
32
57
  end
33
58
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Uffizzi
4
- VERSION = '0.3.7'
4
+ VERSION = '0.5.0'
5
5
  end
data/lib/uffizzi.rb CHANGED
@@ -3,6 +3,8 @@
3
3
  require 'io/console'
4
4
  require 'tty-spinner'
5
5
 
6
+ require 'thor'
7
+ require 'uffizzi/error'
6
8
  require 'uffizzi/shell'
7
9
  require 'uffizzi/version'
8
10
  require 'uffizzi/clients/api/api_client'
@@ -11,8 +13,6 @@ require 'uffizzi/config_file'
11
13
  require_relative '../config/uffizzi'
12
14
 
13
15
  module Uffizzi
14
- class Error < StandardError; end
15
-
16
16
  class << self
17
17
  def ui
18
18
  @ui ||= Uffizzi::UI::Shell.new
data/man/uffizzi ADDED
@@ -0,0 +1,51 @@
1
+ .\" generated with Ronn-NG/v0.9.1
2
+ .\" http://github.com/apjanke/ronn-ng/tree/0.9.1
3
+ .TH "UFFIZZI" "" "April 2022" ""
4
+ .SH "NAME"
5
+ \fBuffizzi\fR \- manage Uffizzi resources
6
+ .SH "SYNOPSIS"
7
+ .nf
8
+ uffizzi GROUP | COMMAND
9
+ .fi
10
+ .SH "DESCRIPTION"
11
+ .nf
12
+ The uffizzi CLI manages authentication, configuration, and
13
+ interaction with Uffizzi APIs\.
14
+
15
+ For more information on the uffizzi CLI, see:
16
+ https://docs\.uffizzi\.com/cli
17
+ .fi
18
+ .SH "GROUP"
19
+ .nf
20
+ GROUP is one of the following:
21
+
22
+ config
23
+ Configure the uffizzi CLI
24
+
25
+ connect
26
+ Grant a Uffizzi user account access to external services
27
+
28
+ preview
29
+ Manage Uffizzi previews and view logs
30
+
31
+ project
32
+ Manage Uffizzi project resources including compose files for
33
+ specifying preview configurations and secrets
34
+ .fi
35
+ .SH "COMMAND"
36
+ .nf
37
+ COMMAND is one of the following:
38
+
39
+ help
40
+ Show uffizzi documentation
41
+
42
+ login
43
+ Log in to a Uffizzi user account
44
+
45
+ logout
46
+ Log out of a Uffizzi user account
47
+
48
+ version
49
+ Print version information for uffizzi CLI
50
+ .fi
51
+