uffizzi-cli 1.0.4 → 2.0.29

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 (156) hide show
  1. checksums.yaml +4 -4
  2. data/config/uffizzi.rb +1 -0
  3. data/lib/uffizzi/auth_helper.rb +13 -5
  4. data/lib/uffizzi/cli/account.rb +122 -0
  5. data/lib/uffizzi/cli/cluster.rb +363 -0
  6. data/lib/uffizzi/cli/common.rb +2 -4
  7. data/lib/uffizzi/cli/config.rb +5 -4
  8. data/lib/uffizzi/cli/connect.rb +14 -8
  9. data/lib/uffizzi/cli/disconnect.rb +1 -1
  10. data/lib/uffizzi/cli/login.rb +130 -66
  11. data/lib/uffizzi/cli/login_by_identity_token.rb +11 -7
  12. data/lib/uffizzi/cli/preview/service.rb +3 -4
  13. data/lib/uffizzi/cli/preview.rb +33 -32
  14. data/lib/uffizzi/cli/project.rb +17 -9
  15. data/lib/uffizzi/cli.rb +46 -7
  16. data/lib/uffizzi/clients/api/api_client.rb +92 -2
  17. data/lib/uffizzi/clients/api/api_routes.rb +44 -0
  18. data/lib/uffizzi/clients/api/http_client.rb +19 -7
  19. data/lib/uffizzi/config_file.rb +15 -40
  20. data/lib/uffizzi/error.rb +15 -0
  21. data/lib/uffizzi/helpers/config_helper.rb +49 -0
  22. data/lib/uffizzi/helpers/file_helper.rb +25 -0
  23. data/lib/uffizzi/helpers/login_helper.rb +33 -0
  24. data/lib/uffizzi/helpers/project_helper.rb +19 -0
  25. data/lib/uffizzi/promt.rb +4 -0
  26. data/lib/uffizzi/response_helper.rb +33 -14
  27. data/lib/uffizzi/services/cluster_service.rb +59 -0
  28. data/lib/uffizzi/services/compose_file_service.rb +5 -4
  29. data/lib/uffizzi/services/env_variables_service.rb +4 -2
  30. data/lib/uffizzi/services/github_service.rb +21 -0
  31. data/lib/uffizzi/services/kubeconfig_service.rb +132 -0
  32. data/lib/uffizzi/services/preview_service.rb +52 -18
  33. data/lib/uffizzi/shell.rb +19 -16
  34. data/lib/uffizzi/token.rb +37 -0
  35. data/lib/uffizzi/version.rb +1 -1
  36. data/lib/uffizzi.rb +10 -0
  37. data/man/uffizzi +7 -5
  38. data/man/uffizzi-account +29 -0
  39. data/man/uffizzi-account-list +26 -0
  40. data/man/uffizzi-account-list.html +103 -0
  41. data/man/uffizzi-account-list.ronn +19 -0
  42. data/man/uffizzi-account-set-default +29 -0
  43. data/man/uffizzi-account-set-default.html +105 -0
  44. data/man/uffizzi-account-set-default.ronn +22 -0
  45. data/man/uffizzi-account.html +106 -0
  46. data/man/uffizzi-account.ronn +23 -0
  47. data/man/uffizzi-cluster +37 -0
  48. data/man/uffizzi-cluster-create +49 -0
  49. data/man/uffizzi-cluster-create.ronn +41 -0
  50. data/man/uffizzi-cluster-delete +32 -0
  51. data/man/uffizzi-cluster-delete.ronn +24 -0
  52. data/man/uffizzi-cluster-describe +39 -0
  53. data/man/uffizzi-cluster-describe.ronn +30 -0
  54. data/man/uffizzi-cluster-list +34 -0
  55. data/man/uffizzi-cluster-list.ronn +26 -0
  56. data/man/uffizzi-cluster-update-kubeconfig +37 -0
  57. data/man/uffizzi-cluster-update-kubeconfig.ronn +29 -0
  58. data/man/uffizzi-cluster.ronn +32 -0
  59. data/man/uffizzi-compose +39 -0
  60. data/man/uffizzi-compose-create +67 -0
  61. data/man/uffizzi-compose-create.ronn +57 -0
  62. data/man/uffizzi-compose-delete +38 -0
  63. data/man/uffizzi-compose-delete.ronn +29 -0
  64. data/man/uffizzi-compose-describe +38 -0
  65. data/man/uffizzi-compose-describe.ronn +29 -0
  66. data/man/uffizzi-compose-events +38 -0
  67. data/man/uffizzi-compose-events.ronn +29 -0
  68. data/man/uffizzi-compose-list +58 -0
  69. data/man/uffizzi-compose-list.ronn +49 -0
  70. data/man/uffizzi-compose-service-list +42 -0
  71. data/man/uffizzi-compose-service-list.ronn +32 -0
  72. data/man/uffizzi-compose-service-logs +59 -0
  73. data/man/uffizzi-compose-service-logs.ronn +48 -0
  74. data/man/uffizzi-compose-update +61 -0
  75. data/man/uffizzi-compose-update.ronn +51 -0
  76. data/man/uffizzi-compose.ronn +33 -0
  77. data/man/uffizzi-compose_service_logs +59 -0
  78. data/man/uffizzi-compose_service_logs.ronn +50 -0
  79. data/man/uffizzi-config +2 -2
  80. data/man/uffizzi-config.ronn +1 -1
  81. data/man/uffizzi-connect +2 -4
  82. data/man/uffizzi-connect-acr +2 -2
  83. data/man/uffizzi-connect-acr.ronn +1 -1
  84. data/man/uffizzi-connect-docker-hub +2 -2
  85. data/man/uffizzi-connect-docker-hub.ronn +1 -1
  86. data/man/uffizzi-connect-docker-registry +2 -2
  87. data/man/uffizzi-connect-docker-registry.ronn +1 -1
  88. data/man/uffizzi-connect-ecr +2 -2
  89. data/man/uffizzi-connect-ecr.ronn +1 -1
  90. data/man/uffizzi-connect-gcr +2 -2
  91. data/man/uffizzi-connect-gcr.ronn +1 -1
  92. data/man/uffizzi-connect-ghcr +2 -2
  93. data/man/uffizzi-connect-ghcr.ronn +1 -1
  94. data/man/uffizzi-connect.ronn +2 -2
  95. data/man/uffizzi-disconnect +2 -2
  96. data/man/uffizzi-disconnect.ronn +1 -1
  97. data/man/uffizzi-login +7 -3
  98. data/man/uffizzi-login-by-identity-token +3 -3
  99. data/man/uffizzi-login-by-identity-token.ronn +2 -2
  100. data/man/uffizzi-login.html +113 -0
  101. data/man/uffizzi-login.ronn +6 -2
  102. data/man/uffizzi-logout +2 -2
  103. data/man/uffizzi-logout.ronn +1 -1
  104. data/man/uffizzi-preview +9 -9
  105. data/man/uffizzi-preview-create +22 -20
  106. data/man/uffizzi-preview-create.ronn +28 -26
  107. data/man/uffizzi-preview-delete +11 -10
  108. data/man/uffizzi-preview-delete.ronn +12 -11
  109. data/man/uffizzi-preview-describe +10 -10
  110. data/man/uffizzi-preview-describe.ronn +11 -11
  111. data/man/uffizzi-preview-events +12 -11
  112. data/man/uffizzi-preview-events.ronn +13 -12
  113. data/man/uffizzi-preview-list +19 -18
  114. data/man/uffizzi-preview-list.ronn +21 -20
  115. data/man/uffizzi-preview-service-list +16 -12
  116. data/man/uffizzi-preview-service-list.ronn +16 -13
  117. data/man/uffizzi-preview-service-logs +14 -12
  118. data/man/uffizzi-preview-service-logs.ronn +18 -17
  119. data/man/uffizzi-preview-update +19 -18
  120. data/man/uffizzi-preview-update.ronn +21 -20
  121. data/man/uffizzi-preview.ronn +10 -10
  122. data/man/uffizzi-preview_service_logs +14 -12
  123. data/man/uffizzi-preview_service_logs.ronn +18 -17
  124. data/man/uffizzi-project +3 -3
  125. data/man/uffizzi-project-compose +2 -2
  126. data/man/uffizzi-project-compose-describe +2 -2
  127. data/man/uffizzi-project-compose-describe.ronn +1 -1
  128. data/man/uffizzi-project-compose-set +2 -2
  129. data/man/uffizzi-project-compose-set.ronn +1 -1
  130. data/man/uffizzi-project-compose-unset +2 -2
  131. data/man/uffizzi-project-compose-unset.ronn +1 -1
  132. data/man/uffizzi-project-compose.ronn +1 -1
  133. data/man/uffizzi-project-create +2 -2
  134. data/man/uffizzi-project-create.ronn +1 -1
  135. data/man/uffizzi-project-delete +2 -2
  136. data/man/uffizzi-project-delete.ronn +1 -1
  137. data/man/uffizzi-project-describe +3 -3
  138. data/man/uffizzi-project-describe.ronn +1 -1
  139. data/man/uffizzi-project-preview-describe +37 -0
  140. data/man/uffizzi-project-preview-describe.ronn +29 -0
  141. data/man/uffizzi-project-preview-set +66 -0
  142. data/man/uffizzi-project-preview-set.ronn +57 -0
  143. data/man/uffizzi-project-secret +2 -2
  144. data/man/uffizzi-project-secret-create +2 -2
  145. data/man/uffizzi-project-secret-create.ronn +1 -1
  146. data/man/uffizzi-project-secret-delete +2 -2
  147. data/man/uffizzi-project-secret-delete.ronn +1 -1
  148. data/man/uffizzi-project-secret-list +2 -2
  149. data/man/uffizzi-project-secret-list.ronn +1 -1
  150. data/man/uffizzi-project-secret.ronn +1 -1
  151. data/man/uffizzi-project-set-default +2 -2
  152. data/man/uffizzi-project-set-default.ronn +1 -1
  153. data/man/uffizzi-project.html +124 -0
  154. data/man/uffizzi-project.ronn +2 -2
  155. data/man/uffizzi.ronn +12 -10
  156. metadata +131 -19
@@ -3,7 +3,11 @@
3
3
  require 'uffizzi'
4
4
  require 'uffizzi/response_helper'
5
5
  require 'uffizzi/helpers/project_helper'
6
+ require 'uffizzi/helpers/login_helper'
7
+ require 'uffizzi/helpers/config_helper'
6
8
  require 'uffizzi/clients/api/api_client'
9
+ require 'launchy'
10
+ require 'securerandom'
7
11
  require 'tty-prompt'
8
12
 
9
13
  module Uffizzi
@@ -12,104 +16,146 @@ module Uffizzi
12
16
 
13
17
  def initialize(options)
14
18
  @options = options
19
+ @server = Uffizzi::LoginHelper.set_server(@options)
15
20
  end
16
21
 
17
22
  def run
18
- Uffizzi.ui.say('Login to Uffizzi server.')
19
- server = set_server
23
+ AuthHelper.sign_out if AuthHelper.signed_in?
24
+ return perform_email_login if @options[:email]
25
+
26
+ perform_browser_login
27
+ end
20
28
 
21
- username = set_username
22
- password = set_password
23
- params = prepare_request_params(username, password)
24
- response = create_session(server, params)
29
+ private
30
+
31
+ def perform_email_login
32
+ Uffizzi.ui.say('Login to Uffizzi server.')
33
+ username = Uffizzi::LoginHelper.set_username(@options)
34
+ password = Uffizzi::LoginHelper.set_password
35
+ params = Uffizzi::LoginHelper.prepare_request_params(username, password)
36
+ response = create_session(@server, params)
25
37
 
26
38
  if ResponseHelper.created?(response)
27
- handle_succeed_response(response, server, username)
39
+ handle_succeed_response(response, username)
28
40
  else
29
41
  ResponseHelper.handle_failed_response(response)
30
42
  end
31
43
  end
32
44
 
33
- private
45
+ def perform_browser_login
46
+ session_id = SecureRandom.uuid
47
+ response = create_access_token(@server, session_id)
48
+ return handle_failed_response(response) unless ResponseHelper.created?(response)
34
49
 
35
- def set_server
36
- config_server = ConfigFile.exists? ? read_option_from_config(:server) : nil
37
- server_address = (@options[:server] || config_server || Uffizzi.ui.ask('Server:')).sub(/\/+$/, '')
38
- server_address.start_with?('http:', 'https:') ? server_address : "https://#{server_address}"
39
- end
50
+ url = browser_sign_in_url(@server, session_id)
51
+ open_browser(url)
40
52
 
41
- def set_username
42
- config_username = ConfigFile.exists? ? read_option_from_config(:username) : nil
43
- @options[:username] || config_username || Uffizzi.ui.ask('Username:')
44
- end
53
+ loop do
54
+ response = get_access_token(@server, session_id)
45
55
 
46
- def set_password
47
- ENV['UFFIZZI_PASSWORD'] || Uffizzi.ui.ask('Password:', echo: false)
56
+ if ResponseHelper.ok?(response)
57
+ break handle_token_success(response)
58
+ elsif ResponseHelper.unprocessable_entity?(response)
59
+ break Uffizzi.ui.say('The session has expired. Please try again.')
60
+ else
61
+ sleep(3)
62
+ end
63
+ end
48
64
  end
49
65
 
50
- def read_option_from_config(option)
51
- ConfigFile.option_has_value?(option) ? ConfigFile.read_option(option) : nil
52
- end
66
+ def handle_token_success(response)
67
+ ConfigFile.write_option(:server, @server)
68
+ token = response[:body][:access_token]
69
+ Uffizzi::Token.delete
70
+ Uffizzi::Token.write(token)
71
+ Uffizzi.ui.say('Login successfull')
53
72
 
54
- def prepare_request_params(username, password)
55
- {
56
- user: {
57
- email: username,
58
- password: password,
59
- },
60
- }
73
+ set_current_account_and_project
61
74
  end
62
75
 
63
- def handle_succeed_response(response, server, username)
64
- # TODO Choose a personal account
65
- account = response[:body][:user][:accounts].first
66
- return Uffizzi.ui.say('No account related to this email') unless account_valid?(account)
76
+ def open_browser(url)
77
+ Launchy.open(url) do |_exception|
78
+ Uffizzi.ui.say('Login to Uffizzi server.')
79
+ Uffizzi.ui.say(url)
80
+ end
81
+ end
67
82
 
68
- ConfigFile.write_option(:server, server)
83
+ def handle_succeed_response(response, username)
84
+ ConfigFile.write_option(:server, @server)
69
85
  ConfigFile.write_option(:username, username)
70
86
  ConfigFile.write_option(:cookie, response[:headers])
71
- ConfigFile.write_option(:account_id, account[:id])
72
-
73
87
  Uffizzi.ui.say('Login successfull')
74
88
 
75
- default_project = ConfigFile.read_option(:project)
76
- return unless default_project
89
+ if ENV.fetch('CI_PIPELINE_RUN', false)
90
+ account = response[:body][:user][:default_account]
91
+ return ConfigFile.write_option(:account, Uffizzi::ConfigHelper.account_config(account[:id]))
92
+ end
77
93
 
78
- check_default_project(default_project, server)
94
+ set_current_account_and_project
79
95
  end
80
96
 
81
- def account_valid?(account)
82
- account[:state] == 'active'
97
+ def set_current_account_and_project
98
+ current_account_id = ConfigFile.read_option(:account, :id)
99
+ current_project_slug = ConfigFile.read_option(:project)
100
+
101
+ unless current_account_id
102
+ account_id = set_account
103
+ return set_project(account_id)
104
+ end
105
+
106
+ return if current_project_slug && project_exists?(current_account_id, current_project_slug)
107
+
108
+ set_project(account_id)
83
109
  end
84
110
 
85
- def check_default_project(default_project, server)
86
- check_project_response = fetch_projects(server)
111
+ def project_exists?(account_id, project_slug)
112
+ check_project_response = fetch_account_projects(@server, account_id)
87
113
  return ResponseHelper.handle_failed_response(check_project_response) unless ResponseHelper.ok?(check_project_response)
88
114
 
89
115
  projects = check_project_response[:body][:projects]
90
116
  slugs = projects.map { |project| project[:slug] }
91
- return if slugs.include?(default_project)
92
117
 
93
- question = "Project '#{default_project}' does not exist. Select one of the following projects or create a new project:"
118
+ slugs.include?(project_slug)
119
+ end
120
+
121
+ def set_account
122
+ accounts_response = fetch_accounts(@server)
123
+ accounts = accounts_response[:body][:accounts]
124
+ if accounts.length == 1
125
+ current_account = accounts.first
126
+ ConfigFile.write_option(:account, Uffizzi::ConfigHelper.account_config(current_account[:id], current_account[:name]))
127
+ return current_account[:id]
128
+ end
129
+ question = 'Select an account:'
130
+ choices = accounts.map do |account|
131
+ { name: account[:name], value: account[:id] }
132
+ end
133
+ account_id = Uffizzi.prompt.select(question, choices)
134
+ account_name = accounts.detect { |account| account[:id] == account_id }[:name]
135
+
136
+ ConfigFile.write_option(:account, Uffizzi::ConfigHelper.account_config(account_id, account_name))
137
+
138
+ account_id
139
+ end
140
+
141
+ def set_project(account_id)
142
+ projects_response = fetch_account_projects(@server, account_id)
143
+ projects = projects_response[:body][:projects]
94
144
  choices = projects.map do |project|
95
145
  { name: project[:name], value: project[:slug] }
96
146
  end
97
147
  all_choices = choices + [{ name: 'Create a new project', value: nil }]
148
+ question = 'Select a project or create a new project:'
98
149
  answer = Uffizzi.prompt.select(question, all_choices)
99
- return create_new_project(server) unless answer
150
+ return create_new_project unless answer
100
151
 
101
- account_id = projects.detect { |project| project[:slug] == answer }[:account_id]
102
152
  ConfigFile.write_option(:project, answer)
103
- ConfigFile.write_option(:account_id, account_id)
104
153
  end
105
154
 
106
- def create_new_project(server)
107
- project_name = Uffizzi.prompt.ask('Project name: ', required: true)
108
- generated_slug = Uffizzi::ProjectHelper.generate_slug(project_name)
109
- project_slug = Uffizzi.prompt.ask('Project slug: ', default: generated_slug)
110
- raise Uffizzi::Error.new('Slug must not content spaces or special characters') unless project_slug.match?(/^[a-zA-Z0-9\-_]+\Z/i)
111
-
112
- project_description = Uffizzi.prompt.ask('Project desciption: ')
155
+ def create_new_project(prev_params = {})
156
+ project_name = Uffizzi.prompt.ask('Project name: ', required: true, default: prev_params.fetch(:name, nil))
157
+ project_slug = ask_project_slug(project_name, prev_params.fetch(:slug, nil))
158
+ project_description = Uffizzi.prompt.ask('Project desciption: ', default: prev_params.fetch(:description, nil))
113
159
 
114
160
  params = {
115
161
  project: {
@@ -119,31 +165,49 @@ module Uffizzi
119
165
  },
120
166
  }
121
167
 
122
- account_id = ConfigFile.read_option(:account_id)
123
- response = create_project(server, account_id, params)
168
+ account_id = ConfigFile.read_option(:account, :id)
169
+ response = create_project(@server, account_id, params)
124
170
 
125
171
  if ResponseHelper.created?(response)
126
172
  handle_create_project_succeess(response)
127
173
  else
128
- handle_create_project_failed(response)
174
+ handle_create_project_failed(response, params[:project])
129
175
  end
130
176
  end
131
177
 
132
- def handle_create_project_failed(response)
133
- name_error = response[:body][:errors][:name].first
134
- name_already_exists = name_error && name_error.first == 'Name already exists'
135
- message = "Project with name #{project_name} already exists. " \
136
- 'Please run $ uffizzi config to set it as a default project'
137
- raise Uffizzi::Error.new(message) if name_already_exists
178
+ def ask_project_slug(project_name, prev_slug = nil)
179
+ generated_slug = Uffizzi::ProjectHelper.generate_slug(project_name)
180
+ default_slug = prev_slug || generated_slug
181
+ project_slug = Uffizzi.prompt.ask('Project slug: ', default: default_slug)
182
+ return project_slug if project_slug.match?(/^[a-zA-Z0-9\-_]+\Z/i)
183
+
184
+ question = 'Slug must not content spaces or special characters. Do you want to a different project slug?'
185
+ answer = Uffizzi.prompt.yes?(question)
186
+ return ask_project_slug(project_name) if answer
187
+
188
+ raise Uffizzi::Error.new('Project creation aborted')
189
+ end
190
+
191
+ def handle_create_project_failed(response, project_params)
192
+ errors = [:name, :slug].map { |error_key| response.dig(:body, :errors, error_key).to_a.first }.compact
193
+
194
+ if errors.blank?
195
+ return ResponseHelper.handle_failed_response(response)
196
+ end
197
+
198
+ Uffizzi.ui.say(errors.join("\n"))
199
+ question = 'Do you want to try different project params?'
200
+ answer = Uffizzi.prompt.yes?(question)
201
+
202
+ return create_new_project(project_params) if answer
138
203
 
139
- ResponseHelper.handle_failed_response(response)
204
+ raise Uffizzi::Error.new("Project creation aborted. You can run 'uffizzi config' to set project as a default")
140
205
  end
141
206
 
142
207
  def handle_create_project_succeess(response)
143
208
  project = response[:body][:project]
144
209
 
145
210
  ConfigFile.write_option(:project, project[:slug])
146
- ConfigFile.write_option(:account_id, project[:account_id])
147
211
 
148
212
  Uffizzi.ui.say("Project #{project[:name]} was successfully created")
149
213
  end
@@ -3,6 +3,7 @@
3
3
  require 'uffizzi'
4
4
  require 'uffizzi/response_helper'
5
5
  require 'uffizzi/clients/api/api_client'
6
+ require 'uffizzi/helpers/config_helper'
6
7
 
7
8
  module Uffizzi
8
9
  class Cli::LoginByIdentityToken
@@ -13,13 +14,14 @@ module Uffizzi
13
14
  end
14
15
 
15
16
  def run
16
- token = @options[:token]
17
+ oidc_token = @options[:oidc_token]
18
+ github_access_token = @options[:access_token]
17
19
  server = @options[:server]
18
- params = prepare_request_params(token)
20
+ params = prepare_request_params(oidc_token, github_access_token)
19
21
  response = create_ci_session(server, params)
20
22
 
21
23
  if ResponseHelper.created?(response)
22
- handle_succeed_response(response, server)
24
+ handle_succeed_response(response, server, oidc_token)
23
25
  else
24
26
  ResponseHelper.handle_failed_response(response)
25
27
  end
@@ -27,19 +29,21 @@ module Uffizzi
27
29
 
28
30
  private
29
31
 
30
- def prepare_request_params(token)
32
+ def prepare_request_params(oidc_token, github_access_token)
31
33
  {
32
34
  user: {
33
- token: token,
35
+ token: oidc_token,
36
+ github_access_token: github_access_token,
34
37
  },
35
38
  }
36
39
  end
37
40
 
38
- def handle_succeed_response(response, server)
41
+ def handle_succeed_response(response, server, oidc_token)
39
42
  ConfigFile.write_option(:server, server)
40
43
  ConfigFile.write_option(:cookie, response[:headers])
41
- ConfigFile.write_option(:account_id, response[:body][:account_id])
44
+ ConfigFile.write_option(:account, Uffizzi::ConfigHelper.account_config(response[:body][:account_id]))
42
45
  ConfigFile.write_option(:project, response[:body][:project_slug])
46
+ ConfigFile.write_option(:oidc_token, oidc_token)
43
47
 
44
48
  Uffizzi.ui.say('Successful Login by Identity Token')
45
49
  end
@@ -26,7 +26,7 @@ module Uffizzi
26
26
  end
27
27
  end
28
28
 
29
- desc 'list [DEPLOYMENT_ID]', 'List the container services of a given preview'
29
+ desc 'list [DEPLOYMENT_ID]', 'List the container services of a given compose environment (preview)'
30
30
  def list(deployment_name)
31
31
  return Uffizzi.ui.say('You are not logged in.') unless Uffizzi::AuthHelper.signed_in?
32
32
  return Uffizzi.ui.say('This command needs project to be set in config file') unless CommandService.project_set?(options)
@@ -70,9 +70,8 @@ module Uffizzi
70
70
  logs = response[:body][:logs] || []
71
71
  return Uffizzi.ui.say("The service '#{container_name}' has no logs") if logs.empty?
72
72
 
73
- logs.each do |log|
74
- Uffizzi.ui.say(log)
75
- end
73
+ logs_columns = logs.map { |log| [log[:timestamp], log[:payload]] }
74
+ Uffizzi.ui.print_table(logs_columns)
76
75
  end
77
76
  end
78
77
  end
@@ -4,47 +4,49 @@ require 'uffizzi'
4
4
  require 'uffizzi/auth_helper'
5
5
  require 'uffizzi/services/preview_service'
6
6
  require 'uffizzi/services/command_service'
7
+ require 'uffizzi/services/github_service'
7
8
 
8
9
  module Uffizzi
9
10
  class Cli::Preview < Thor
10
11
  include ApiClient
11
12
 
12
- desc 'service', 'Show the preview services info'
13
+ desc 'service', 'Show the compose environment (preview) services info'
13
14
  require_relative 'preview/service'
14
15
  subcommand 'service', Uffizzi::Cli::Preview::Service
15
16
 
16
- desc 'list', 'List all previews'
17
+ desc 'list', 'List all compose environments (previews)'
17
18
  method_option :filter, required: false, type: :string, aliases: '-f'
18
19
  method_option :output, required: false, type: :string, aliases: '-o', enum: ['json', 'pretty-json']
19
20
  def list
20
21
  run('list')
21
22
  end
22
23
 
23
- desc 'create [COMPOSE_FILE]', 'Create a preview'
24
+ desc 'create [COMPOSE_FILE]', 'Create a compose environment (preview)'
24
25
  method_option :output, required: false, type: :string, aliases: '-o', enum: ['json', 'github-action']
25
26
  method_option :"set-labels", required: false, type: :string, aliases: '-s'
27
+ method_option :"creation-source", required: false, type: :string
26
28
  def create(file_path = nil)
27
29
  run('create', file_path: file_path)
28
30
  end
29
31
 
30
- desc 'uffizzi preview update [DEPLOYMENT_ID] [COMPOSE_FILE]', 'Update a preview'
32
+ desc 'update [DEPLOYMENT_ID] [COMPOSE_FILE]', 'Update a compose environment (preview)'
31
33
  method_option :output, required: false, type: :string, aliases: '-o', enum: ['json', 'github-action']
32
34
  method_option :"set-labels", required: false, type: :string, aliases: '-s'
33
35
  def update(deployment_name, file_path)
34
36
  run('update', deployment_name: deployment_name, file_path: file_path)
35
37
  end
36
38
 
37
- desc 'delete [DEPLOYMENT_ID]', 'Delete a preview'
39
+ desc 'delete [DEPLOYMENT_ID]', 'Delete a compose environment (preview)'
38
40
  def delete(deployment_name)
39
41
  run('delete', deployment_name: deployment_name)
40
42
  end
41
43
 
42
- desc 'describe [DEPLOYMENT_ID]', 'Display details of a preview'
44
+ desc 'describe [DEPLOYMENT_ID]', 'Display details of a compose environment (preview)'
43
45
  def describe(deployment_name)
44
46
  run('describe', deployment_name: deployment_name)
45
47
  end
46
48
 
47
- desc 'events [DEPLOYMENT_ID]', 'Show the deployment event logs for a preview'
49
+ desc 'events [DEPLOYMENT_ID]', 'Show the deployment event logs for a compose environment (preview)'
48
50
  def events(deployment_name)
49
51
  run('events', deployment_name: deployment_name)
50
52
  end
@@ -62,7 +64,7 @@ module Uffizzi
62
64
  when 'list'
63
65
  handle_list_command(project_slug, options[:filter])
64
66
  when 'create'
65
- handle_create_command(file_path, project_slug, options[:"set-labels"])
67
+ handle_create_command(file_path, project_slug, options[:"set-labels"], options[:"creation-source"])
66
68
  when 'update'
67
69
  handle_update_command(deployment_name, file_path, project_slug, options[:"set-labels"])
68
70
  when 'delete'
@@ -85,10 +87,9 @@ module Uffizzi
85
87
  end
86
88
  end
87
89
 
88
- def handle_create_command(file_path, project_slug, labels)
89
- Uffizzi.ui.disable_stdout unless options[:output].nil?
90
-
91
- params = prepare_params(file_path, labels)
90
+ def handle_create_command(file_path, project_slug, labels, creation_source)
91
+ Uffizzi.ui.disable_stdout if Uffizzi.ui.output_format
92
+ params = prepare_params(file_path, labels, creation_source)
92
93
 
93
94
  response = create_deployment(ConfigFile.read_option(:server), project_slug, params)
94
95
 
@@ -98,17 +99,18 @@ module Uffizzi
98
99
 
99
100
  deployment = response[:body][:deployment]
100
101
  Uffizzi.ui.say("Preview with ID deployment-#{deployment[:id]} was created.")
102
+ deployment_data = build_deployment_data(deployment)
103
+ Uffizzi.ui.say("Deployment details url: #{deployment_data[:containers_uri]}")
101
104
 
102
- success = PreviewService.run_containers_deploy(project_slug, deployment)
103
-
104
- display_deployment_data(deployment, success)
105
+ PreviewService.run_containers_deploy(project_slug, deployment)
106
+ handle_result(deployment_data)
105
107
  rescue SystemExit, Interrupt, SocketError
106
108
  deployment_id = response[:body][:deployment][:id]
107
109
  handle_preview_interruption(deployment_id, ConfigFile.read_option(:server), project_slug)
108
110
  end
109
111
 
110
112
  def handle_update_command(deployment_name, file_path, project_slug, labels)
111
- Uffizzi.ui.disable_stdout unless options[:output].nil?
113
+ Uffizzi.ui.disable_stdout if Uffizzi.ui.output_format
112
114
  deployment_id = PreviewService.read_deployment_id(deployment_name)
113
115
 
114
116
  raise Uffizzi::Error.new("Preview should be specified in 'deployment-PREVIEW_ID' format") if deployment_id.nil?
@@ -122,10 +124,11 @@ module Uffizzi
122
124
 
123
125
  deployment = response[:body][:deployment]
124
126
  Uffizzi.ui.say("Preview with ID deployment-#{deployment_id} was updated.")
127
+ deployment_data = build_deployment_data(deployment)
128
+ Uffizzi.ui.say("Deployment details url: #{deployment_data[:containers_uri]}")
125
129
 
126
- success = PreviewService.run_containers_deploy(project_slug, deployment)
127
-
128
- display_deployment_data(deployment, success)
130
+ PreviewService.run_containers_deploy(project_slug, deployment)
131
+ handle_result(deployment_data)
129
132
  rescue SystemExit, Interrupt, SocketError
130
133
  deployment_id = response[:body][:deployment][:id]
131
134
  handle_preview_interruption(deployment_id, ConfigFile.read_option(:server), project_slug)
@@ -215,10 +218,13 @@ module Uffizzi
215
218
  end
216
219
  end
217
220
 
218
- def prepare_params(file_path, labels)
221
+ def prepare_params(file_path, labels, creation_source = nil)
219
222
  compose_file_params = file_path.nil? ? {} : build_compose_file_params(file_path)
220
223
  metadata_params = labels.nil? ? {} : build_metadata_params(labels)
221
- compose_file_params.merge(metadata_params)
224
+ oidc_token = ConfigFile.read_option(:oidc_token)
225
+ extra_params = oidc_token.nil? ? {} : { token: oidc_token }
226
+ params = compose_file_params.merge(metadata_params)
227
+ params.merge(extra_params, { creation_source: creation_source })
222
228
  end
223
229
 
224
230
  def handle_preview_interruption(deployment_id, server, project_slug)
@@ -227,22 +233,16 @@ module Uffizzi
227
233
  preview_deletion_message = if ResponseHelper.no_content?(deletion_response)
228
234
  "The preview #{deployment_name} has been disabled."
229
235
  else
230
- "Couldn't disable the deployment #{deployment_name} - please disable maually."
236
+ "Couldn't disable the deployment #{deployment_name} - please disable manually."
231
237
  end
232
238
 
233
239
  raise Uffizzi::Error.new("The preview creation was interrupted. #{preview_deletion_message}")
234
240
  end
235
241
 
236
- def display_deployment_data(deployment, success)
237
- if Uffizzi.ui.output_format.nil?
238
- Uffizzi.ui.say('Done')
239
- preview_url = "https://#{deployment[:preview_url]}"
240
- Uffizzi.ui.say(preview_url) if success
241
- else
242
- deployment_data = build_deployment_data(deployment)
243
- Uffizzi.ui.enable_stdout
244
- Uffizzi.ui.say(deployment_data)
245
- end
242
+ def handle_result(deployment_data)
243
+ Uffizzi.ui.enable_stdout
244
+ Uffizzi.ui.say(deployment_data) if Uffizzi.ui.output_format
245
+ GithubService.write_to_github_env(deployment_data) if GithubService.github_actions_exists?
246
246
  end
247
247
 
248
248
  def build_deployment_data(deployment)
@@ -251,6 +251,7 @@ module Uffizzi
251
251
  {
252
252
  id: "deployment-#{deployment[:id]}",
253
253
  url: "https://#{deployment[:preview_url]}",
254
+ proxy_url: "https://#{deployment[:proxy_preview_url]}",
254
255
  containers_uri: "#{url_server}/projects/#{deployment[:project_id]}/deployments/#{deployment[:id]}/containers",
255
256
  }
256
257
  end
@@ -4,6 +4,7 @@ require 'uffizzi'
4
4
  require 'uffizzi/auth_helper'
5
5
  require 'uffizzi/response_helper'
6
6
  require 'uffizzi/helpers/project_helper'
7
+ require 'uffizzi/helpers/config_helper'
7
8
  require 'uffizzi/services/project_service'
8
9
 
9
10
  module Uffizzi
@@ -36,6 +37,7 @@ module Uffizzi
36
37
  end
37
38
 
38
39
  map('set-default' => :set_default)
40
+ map('set' => :set_default)
39
41
 
40
42
  method_option :name, required: true
41
43
  method_option :slug, default: ''
@@ -70,7 +72,7 @@ module Uffizzi
70
72
  end
71
73
 
72
74
  def handle_describe_command(project_slug)
73
- response = describe_project(ConfigFile.read_option(:server), project_slug)
75
+ response = fetch_project(ConfigFile.read_option(:server), project_slug)
74
76
 
75
77
  if ResponseHelper.ok?(response)
76
78
  handle_succeed_describe_response(response)
@@ -87,7 +89,8 @@ module Uffizzi
87
89
 
88
90
  def handle_list_command
89
91
  server = ConfigFile.read_option(:server)
90
- response = fetch_projects(server)
92
+ account_id = ConfigFile.read_option(:account, :id)
93
+ response = fetch_account_projects(server, account_id)
91
94
 
92
95
  if ResponseHelper.ok?(response)
93
96
  handle_list_success_response(response)
@@ -102,7 +105,8 @@ module Uffizzi
102
105
  raise Uffizzi::Error.new('Slug must not content spaces or special characters') unless slug.match?(/^[a-zA-Z0-9\-_]+\Z/i)
103
106
 
104
107
  server = ConfigFile.read_option(:server)
105
- account_id = ConfigFile.read_option(:account_id)
108
+ account_id = ConfigFile.read_option(:account, :id)
109
+
106
110
  params = {
107
111
  name: name,
108
112
  description: options[:description],
@@ -130,14 +134,14 @@ module Uffizzi
130
134
 
131
135
  def handle_list_success_response(response)
132
136
  projects = response[:body][:projects]
133
- return Uffizzi.ui.say('No projects related to this email') if projects.empty?
137
+ return Uffizzi.ui.say('No projects found') if projects.empty?
134
138
 
135
139
  set_default_project(projects.first) if projects.size == 1
136
140
  print_projects(projects)
137
141
  end
138
142
 
139
143
  def handle_set_default_command(project_slug)
140
- response = describe_project(ConfigFile.read_option(:server), project_slug)
144
+ response = fetch_project(ConfigFile.read_option(:server), project_slug)
141
145
 
142
146
  if ResponseHelper.ok?(response)
143
147
  handle_succeed_set_default_response(response)
@@ -152,9 +156,9 @@ module Uffizzi
152
156
  end
153
157
 
154
158
  def handle_create_success_response(response)
155
- project_name = response[:body][:project][:name]
156
-
157
- Uffizzi.ui.say("Project #{project_name} was successfully created")
159
+ project = response[:body][:project]
160
+ ConfigFile.write_option(:project, project[:slug])
161
+ Uffizzi.ui.say("Project '#{project[:name]}' with slug '#{project[:slug]}' was successfully created")
158
162
  end
159
163
 
160
164
  def print_projects(projects)
@@ -166,7 +170,11 @@ module Uffizzi
166
170
 
167
171
  def set_default_project(project)
168
172
  ConfigFile.write_option(:project, project[:slug])
169
- ConfigFile.write_option(:account_id, project[:account_id])
173
+ account = project[:account]
174
+ return ConfigFile.write_option(:account, Uffizzi::ConfigHelper.account_config(account[:id], account[:name])) if account
175
+
176
+ # For core versions < core_v2.2.3
177
+ ConfigFile.write_option(:account, Uffizzi::ConfigHelper.account_config(project[:account_id]))
170
178
  end
171
179
  end
172
180
  end