uffizzi-cli 0.7.3 → 0.10.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.
- checksums.yaml +4 -4
- data/README.md +6 -0
- data/config/uffizzi.rb +1 -1
- data/lib/uffizzi/auth_helper.rb +5 -0
- data/lib/uffizzi/cli/config.rb +1 -1
- data/lib/uffizzi/cli/connect.rb +54 -31
- data/lib/uffizzi/cli/disconnect.rb +1 -1
- data/lib/uffizzi/cli/login.rb +76 -2
- data/lib/uffizzi/cli/logout.rb +1 -1
- data/lib/uffizzi/cli/preview.rb +43 -16
- data/lib/uffizzi/cli/project.rb +82 -2
- data/lib/uffizzi/cli.rb +3 -1
- data/lib/uffizzi/clients/api/api_client.rb +15 -1
- data/lib/uffizzi/config_file.rb +14 -20
- data/lib/uffizzi/helpers/project_helper.rb +22 -0
- data/lib/uffizzi/promt.rb +21 -0
- data/lib/uffizzi/services/preview_service.rb +13 -25
- data/lib/uffizzi/services/project_service.rb +40 -0
- data/lib/uffizzi/version.rb +1 -1
- data/lib/uffizzi.rb +5 -0
- data/man/uffizzi +2 -2
- data/man/uffizzi-config +2 -2
- data/man/uffizzi-config.ronn +1 -1
- data/man/uffizzi-connect +2 -2
- data/man/uffizzi-connect-acr +2 -2
- data/man/uffizzi-connect-acr.ronn +1 -1
- data/man/uffizzi-connect-docker-hub +2 -2
- data/man/uffizzi-connect-docker-hub.ronn +1 -1
- data/man/uffizzi-connect-ecr +2 -2
- data/man/uffizzi-connect-ecr.ronn +1 -1
- data/man/uffizzi-connect-gcr +2 -2
- data/man/uffizzi-connect-gcr.ronn +1 -1
- data/man/uffizzi-connect-ghcr +2 -2
- data/man/uffizzi-connect-ghcr.ronn +1 -1
- data/man/uffizzi-connect.ronn +1 -1
- data/man/uffizzi-disconnect +2 -2
- data/man/uffizzi-disconnect.ronn +1 -1
- data/man/uffizzi-login +2 -2
- data/man/uffizzi-login.ronn +1 -1
- data/man/uffizzi-logout +2 -2
- data/man/uffizzi-logout.ronn +1 -1
- data/man/uffizzi-preview +2 -2
- data/man/uffizzi-preview-create +2 -2
- data/man/uffizzi-preview-create.ronn +1 -1
- data/man/uffizzi-preview-delete +2 -2
- data/man/uffizzi-preview-delete.ronn +1 -1
- data/man/uffizzi-preview-describe +2 -2
- data/man/uffizzi-preview-describe.ronn +1 -1
- data/man/uffizzi-preview-events +2 -2
- data/man/uffizzi-preview-events.ronn +1 -1
- data/man/uffizzi-preview-list +2 -2
- data/man/uffizzi-preview-list.ronn +1 -1
- data/man/uffizzi-preview-service-list +2 -2
- data/man/uffizzi-preview-service-list.ronn +1 -1
- data/man/uffizzi-preview-service-logs +2 -2
- data/man/uffizzi-preview-service-logs.ronn +1 -1
- data/man/uffizzi-preview-update +20 -12
- data/man/uffizzi-preview-update.ronn +6 -6
- data/man/uffizzi-preview.ronn +1 -1
- data/man/uffizzi-preview_service_logs +2 -2
- data/man/uffizzi-preview_service_logs.ronn +1 -1
- data/man/uffizzi-project +2 -2
- data/man/uffizzi-project-compose +2 -2
- data/man/uffizzi-project-compose-describe +2 -2
- data/man/uffizzi-project-compose-describe.ronn +1 -1
- data/man/uffizzi-project-compose-set +2 -2
- data/man/uffizzi-project-compose-set.ronn +1 -1
- data/man/uffizzi-project-compose-unset +2 -2
- data/man/uffizzi-project-compose-unset.ronn +1 -1
- data/man/uffizzi-project-compose.ronn +1 -1
- data/man/uffizzi-project-create +50 -0
- data/man/uffizzi-project-create.ronn +41 -0
- data/man/uffizzi-project-delete +32 -0
- data/man/uffizzi-project-delete.ronn +24 -0
- data/man/uffizzi-project-describe +43 -0
- data/man/uffizzi-project-describe.ronn +34 -0
- data/man/uffizzi-project-secret +2 -2
- data/man/uffizzi-project-secret-create +2 -2
- data/man/uffizzi-project-secret-create.ronn +1 -1
- data/man/uffizzi-project-secret-delete +2 -2
- data/man/uffizzi-project-secret-delete.ronn +1 -1
- data/man/uffizzi-project-secret-list +2 -2
- data/man/uffizzi-project-secret-list.ronn +1 -1
- data/man/uffizzi-project-secret.ronn +1 -1
- data/man/uffizzi-project-set-default +2 -2
- data/man/uffizzi-project-set-default.ronn +1 -1
- data/man/uffizzi-project.ronn +1 -1
- data/man/uffizzi.html +1 -1
- data/man/uffizzi.ronn +1 -1
- metadata +25 -22
- data/man/uffizzi-config.html +0 -144
- data/man/uffizzi-login.html +0 -113
- data/man/uffizzi-logout.html +0 -102
- data/man/uffizzi-preview-create.html +0 -128
- data/man/uffizzi-preview-delete.html +0 -115
- data/man/uffizzi-preview-describe.html +0 -116
- data/man/uffizzi-preview-events.html +0 -110
- data/man/uffizzi-preview-list.html +0 -110
- data/man/uffizzi-preview.html +0 -120
- data/man/uffizzi-preview_service_logs.html +0 -142
- data/man/uffizzi-project-compose-describe.html +0 -118
- data/man/uffizzi-project-compose-set.html +0 -149
- data/man/uffizzi-project-compose-unset.html +0 -116
- data/man/uffizzi-project-compose.html +0 -123
- data/man/uffizzi-project-secret-create.html +0 -110
- data/man/uffizzi-project-secret-delete.html +0 -110
- data/man/uffizzi-project-secret-list.html +0 -110
- data/man/uffizzi-project-secret.html +0 -119
- data/man/uffizzi-project-set-default.html +0 -111
- data/man/uffizzi-project.html +0 -128
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e1bc2ece2185acfc991e128222d85edd8f23c3dba70797090a4e0c26cbad3104
|
|
4
|
+
data.tar.gz: f0c2497de38303117159dfc170b9a9c447a61f2ee12b6f9aecef09e1565a1212
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7b50904992dbd671ad3b69d7f056f7d18cd9a7d9912f4a31ffa8ab9b55a687265b501b5f63d35205d6dced804a67ad5389ebdb9020523c79bf163a0932a6662b
|
|
7
|
+
data.tar.gz: 3345ab6d4dbb824c0811771247e76a46710efe77e9b2939903366e7c24bb13ade2e5f00458bc9e67db07610f2d4c5aebfb6d0a20371282792bc30b7b5379f7b1
|
data/README.md
CHANGED
|
@@ -177,3 +177,9 @@ Supported credential types - `docker-hub`, `acr`, `ecr`, `gcr`
|
|
|
177
177
|
## Contributing
|
|
178
178
|
|
|
179
179
|
Bug reports and pull requests are welcome on GitHub at https://github.com/UffizziCloud/uffizzi_cli. See `CONTRIBUTING.md` in this repository.
|
|
180
|
+
|
|
181
|
+
## License
|
|
182
|
+
|
|
183
|
+
This project is licensed under the terms of the Apache-2.0 license.
|
|
184
|
+
|
|
185
|
+
See this license at [`LICENSE`](LICENSE).
|
data/config/uffizzi.rb
CHANGED
|
@@ -18,7 +18,7 @@ module Uffizzi
|
|
|
18
18
|
azure: 'UffizziCore::Credential::Azure',
|
|
19
19
|
google: 'UffizziCore::Credential::Google',
|
|
20
20
|
amazon: 'UffizziCore::Credential::Amazon',
|
|
21
|
-
|
|
21
|
+
github_registry: 'UffizziCore::Credential::GithubContainerRegistry',
|
|
22
22
|
}
|
|
23
23
|
config.default_server = 'app.uffizzi.com'
|
|
24
24
|
end
|
data/lib/uffizzi/auth_helper.rb
CHANGED
data/lib/uffizzi/cli/config.rb
CHANGED
|
@@ -58,7 +58,7 @@ module Uffizzi
|
|
|
58
58
|
\nUffizzi API service and manage previews.\n")
|
|
59
59
|
server = Uffizzi.ui.ask('Server: ', default: Uffizzi.configuration.default_server.to_s)
|
|
60
60
|
username = Uffizzi.ui.ask('Username: ')
|
|
61
|
-
project = Uffizzi.ui.ask('Project: ')
|
|
61
|
+
project = Uffizzi.ui.ask('Project: ', default: 'default')
|
|
62
62
|
ConfigFile.delete
|
|
63
63
|
ConfigFile.write_option(:server, server)
|
|
64
64
|
ConfigFile.write_option(:username, username)
|
data/lib/uffizzi/cli/connect.rb
CHANGED
|
@@ -18,12 +18,14 @@ module Uffizzi
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
desc 'docker-hub', 'Connect to Docker Hub (hub.docker.com)'
|
|
21
|
+
method_option :skip_raise_existence_error, type: :boolean, default: false,
|
|
22
|
+
desc: 'Skip raising an error within check the credential'
|
|
21
23
|
def docker_hub
|
|
22
24
|
type = Uffizzi.configuration.credential_types[:dockerhub]
|
|
23
|
-
|
|
25
|
+
check_credential_existence(type, 'docker-hub')
|
|
24
26
|
|
|
25
|
-
username = Uffizzi.ui.ask('Username: ')
|
|
26
|
-
password = Uffizzi.ui.ask('Password: ', echo: false)
|
|
27
|
+
username = ENV['DOCKERHUB_USERNAME'] || Uffizzi.ui.ask('Username: ')
|
|
28
|
+
password = ENV['DOCKERHUB_PASSWORD'] || Uffizzi.ui.ask('Password: ', echo: false)
|
|
27
29
|
|
|
28
30
|
params = {
|
|
29
31
|
username: username,
|
|
@@ -42,18 +44,20 @@ module Uffizzi
|
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
desc 'acr', 'Connect to Azure Container Registry (azurecr.io)'
|
|
47
|
+
method_option :skip_raise_existence_error, type: :boolean, default: false,
|
|
48
|
+
desc: 'Skip raising an error within check the credential'
|
|
45
49
|
def acr
|
|
46
50
|
type = Uffizzi.configuration.credential_types[:azure]
|
|
47
|
-
|
|
51
|
+
check_credential_existence(type, 'acr')
|
|
48
52
|
|
|
49
|
-
registry_url =
|
|
50
|
-
username = Uffizzi.ui.ask('Docker ID: ')
|
|
51
|
-
password = Uffizzi.ui.ask('Password/Access Token: ', echo: false)
|
|
53
|
+
registry_url = ENV['ACR_REGISTRY_URL'] || Uffizzi.ui.ask('Registry Domain: ')
|
|
54
|
+
username = ENV['ACR_USERNAME'] || Uffizzi.ui.ask('Docker ID: ')
|
|
55
|
+
password = ENV['ACR_PASSWORD'] || Uffizzi.ui.ask('Password/Access Token: ', echo: false)
|
|
52
56
|
|
|
53
57
|
params = {
|
|
54
58
|
username: username,
|
|
55
59
|
password: password,
|
|
56
|
-
registry_url: registry_url,
|
|
60
|
+
registry_url: prepare_registry_url(registry_url),
|
|
57
61
|
type: type,
|
|
58
62
|
}
|
|
59
63
|
|
|
@@ -68,18 +72,20 @@ module Uffizzi
|
|
|
68
72
|
end
|
|
69
73
|
|
|
70
74
|
desc 'ecr', 'Connect to Amazon Elastic Container Registry'
|
|
75
|
+
method_option :skip_raise_existence_error, type: :boolean, default: false,
|
|
76
|
+
desc: 'Skip raising an error within check the credential'
|
|
71
77
|
def ecr
|
|
72
78
|
type = Uffizzi.configuration.credential_types[:amazon]
|
|
73
|
-
|
|
79
|
+
check_credential_existence(type, 'ecr')
|
|
74
80
|
|
|
75
|
-
registry_url =
|
|
76
|
-
|
|
77
|
-
|
|
81
|
+
registry_url = ENV['AWS_REGISTRY_URL'] || Uffizzi.ui.ask('Registry Domain: ')
|
|
82
|
+
access_key = ENV['AWS_ACCESS_KEY_ID'] || Uffizzi.ui.ask('Access key ID: ')
|
|
83
|
+
secret_access_key = ENV['AWS_SECRET_ACCESS_KEY'] || Uffizzi.ui.ask('Secret access key: ', echo: false)
|
|
78
84
|
|
|
79
85
|
params = {
|
|
80
|
-
username:
|
|
81
|
-
password:
|
|
82
|
-
registry_url: registry_url,
|
|
86
|
+
username: access_key,
|
|
87
|
+
password: secret_access_key,
|
|
88
|
+
registry_url: prepare_registry_url(registry_url),
|
|
83
89
|
type: type,
|
|
84
90
|
}
|
|
85
91
|
|
|
@@ -94,17 +100,13 @@ module Uffizzi
|
|
|
94
100
|
end
|
|
95
101
|
|
|
96
102
|
desc 'gcr', 'Connect to Google Container Registry (gcr.io)'
|
|
103
|
+
method_option :skip_raise_existence_error, type: :boolean, default: false,
|
|
104
|
+
desc: 'Skip raising an error within check the credential'
|
|
97
105
|
def gcr(credential_file_path = nil)
|
|
98
106
|
type = Uffizzi.configuration.credential_types[:google]
|
|
99
|
-
|
|
107
|
+
check_credential_existence(type, 'gcr')
|
|
100
108
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
begin
|
|
104
|
-
credential_content = File.read(credential_file_path)
|
|
105
|
-
rescue Errno::ENOENT => e
|
|
106
|
-
return Uffizzi.ui.say(e)
|
|
107
|
-
end
|
|
109
|
+
credential_content = google_service_account_content(credential_file_path)
|
|
108
110
|
|
|
109
111
|
params = {
|
|
110
112
|
password: credential_content,
|
|
@@ -122,12 +124,14 @@ module Uffizzi
|
|
|
122
124
|
end
|
|
123
125
|
|
|
124
126
|
desc 'ghcr', 'Connect to GitHub Container Registry (ghcr.io)'
|
|
127
|
+
method_option :skip_raise_existence_error, type: :boolean, default: false,
|
|
128
|
+
desc: 'Skip raising an error within check the credential'
|
|
125
129
|
def ghcr
|
|
126
|
-
type = Uffizzi.configuration.credential_types[:
|
|
127
|
-
|
|
130
|
+
type = Uffizzi.configuration.credential_types[:github_registry]
|
|
131
|
+
check_credential_existence(type, 'ghcr')
|
|
128
132
|
|
|
129
|
-
username = Uffizzi.ui.ask('Github Username: ')
|
|
130
|
-
password = Uffizzi.ui.ask('Access Token: ', echo: false)
|
|
133
|
+
username = ENV['GITHUB_USERNAME'] || Uffizzi.ui.ask('Github Username: ')
|
|
134
|
+
password = ENV['GITHUB_ACCESS_TOKEN'] || Uffizzi.ui.ask('Access Token: ', echo: false)
|
|
131
135
|
|
|
132
136
|
params = {
|
|
133
137
|
username: username,
|
|
@@ -160,14 +164,19 @@ module Uffizzi
|
|
|
160
164
|
Uffizzi.ui.say("Successfully connected to #{connection_name}")
|
|
161
165
|
end
|
|
162
166
|
|
|
163
|
-
def
|
|
167
|
+
def check_credential_existence(type, connection_name)
|
|
164
168
|
server = ConfigFile.read_option(:server)
|
|
165
169
|
response = check_credential(server, type)
|
|
166
170
|
return if ResponseHelper.ok?(response)
|
|
167
171
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
172
|
+
if options.skip_raise_existence_error?
|
|
173
|
+
Uffizzi.ui.say("Credentials of type #{connection_name} already exist for this account.")
|
|
174
|
+
exit(true)
|
|
175
|
+
else
|
|
176
|
+
message = "Credentials of type #{connection_name} already exist for this account. " \
|
|
177
|
+
"To remove them, run $ uffizzi disconnect #{connection_name}."
|
|
178
|
+
raise Uffizzi::Error.new(message)
|
|
179
|
+
end
|
|
171
180
|
end
|
|
172
181
|
|
|
173
182
|
def handle_list_credentials_success(response)
|
|
@@ -189,5 +198,19 @@ module Uffizzi
|
|
|
189
198
|
|
|
190
199
|
map[credential]
|
|
191
200
|
end
|
|
201
|
+
|
|
202
|
+
def google_service_account_content(credential_file_path = nil)
|
|
203
|
+
return ENV['GCLOUD_SERVICE_KEY'] if ENV['GCLOUD_SERVICE_KEY']
|
|
204
|
+
|
|
205
|
+
return Uffizzi.ui.say('Path to google service account key file wasn\'t specified.') if credential_file_path.nil?
|
|
206
|
+
|
|
207
|
+
begin
|
|
208
|
+
credential_content = File.read(credential_file_path)
|
|
209
|
+
rescue Errno::ENOENT => e
|
|
210
|
+
raise Uffizzi::Error.new(e.message)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
credential_content
|
|
214
|
+
end
|
|
192
215
|
end
|
|
193
216
|
end
|
|
@@ -17,7 +17,7 @@ module Uffizzi
|
|
|
17
17
|
when 'gcr'
|
|
18
18
|
Uffizzi.configuration.credential_types[:google]
|
|
19
19
|
when 'ghcr'
|
|
20
|
-
Uffizzi.configuration.credential_types[:
|
|
20
|
+
Uffizzi.configuration.credential_types[:github_registry]
|
|
21
21
|
else
|
|
22
22
|
raise Uffizzi::Error.new('Unsupported credential type.')
|
|
23
23
|
end
|
data/lib/uffizzi/cli/login.rb
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
require 'uffizzi'
|
|
4
4
|
require 'uffizzi/response_helper'
|
|
5
|
+
require 'uffizzi/helpers/project_helper'
|
|
5
6
|
require 'uffizzi/clients/api/api_client'
|
|
7
|
+
require 'tty-prompt'
|
|
6
8
|
|
|
7
9
|
module Uffizzi
|
|
8
10
|
class Cli::Login
|
|
@@ -15,6 +17,7 @@ module Uffizzi
|
|
|
15
17
|
def run
|
|
16
18
|
Uffizzi.ui.say('Login to Uffizzi to view and manage your previews.')
|
|
17
19
|
server = set_server
|
|
20
|
+
|
|
18
21
|
username = set_username
|
|
19
22
|
password = set_password
|
|
20
23
|
params = prepare_request_params(username, password)
|
|
@@ -30,12 +33,12 @@ module Uffizzi
|
|
|
30
33
|
private
|
|
31
34
|
|
|
32
35
|
def set_server
|
|
33
|
-
config_server = ConfigFile.exists?
|
|
36
|
+
config_server = ConfigFile.exists? ? read_option_from_config(:server) : nil
|
|
34
37
|
@options[:server] || config_server || Uffizzi.ui.ask('Server: ')
|
|
35
38
|
end
|
|
36
39
|
|
|
37
40
|
def set_username
|
|
38
|
-
config_username = ConfigFile.exists?
|
|
41
|
+
config_username = ConfigFile.exists? ? read_option_from_config(:username) : nil
|
|
39
42
|
@options[:username] || config_username || Uffizzi.ui.ask('Username: ')
|
|
40
43
|
end
|
|
41
44
|
|
|
@@ -43,6 +46,10 @@ module Uffizzi
|
|
|
43
46
|
ENV['UFFIZZI_PASSWORD'] || Uffizzi.ui.ask('Password: ', echo: false)
|
|
44
47
|
end
|
|
45
48
|
|
|
49
|
+
def read_option_from_config(option)
|
|
50
|
+
ConfigFile.option_has_value?(option) ? ConfigFile.read_option(option) : nil
|
|
51
|
+
end
|
|
52
|
+
|
|
46
53
|
def prepare_request_params(username, password)
|
|
47
54
|
{
|
|
48
55
|
user: {
|
|
@@ -60,10 +67,77 @@ module Uffizzi
|
|
|
60
67
|
ConfigFile.write_option(:username, username)
|
|
61
68
|
ConfigFile.write_option(:cookie, response[:headers])
|
|
62
69
|
ConfigFile.write_option(:account_id, account[:id])
|
|
70
|
+
|
|
71
|
+
default_project = ConfigFile.read_option(:project)
|
|
72
|
+
return unless default_project
|
|
73
|
+
|
|
74
|
+
check_default_project(default_project, server)
|
|
63
75
|
end
|
|
64
76
|
|
|
65
77
|
def account_valid?(account)
|
|
66
78
|
account[:state] == 'active'
|
|
67
79
|
end
|
|
80
|
+
|
|
81
|
+
def check_default_project(default_project, server)
|
|
82
|
+
check_project_response = fetch_projects(server)
|
|
83
|
+
return ResponseHelper.handle_failed_response(check_project_response) unless ResponseHelper.ok?(check_project_response)
|
|
84
|
+
|
|
85
|
+
projects = check_project_response[:body][:projects]
|
|
86
|
+
slugs = projects.map { |project| project[:slug] }
|
|
87
|
+
return if slugs.include?(default_project)
|
|
88
|
+
|
|
89
|
+
question = "Project '#{default_project}' does not exist. Select one of the following projects or create a new project:"
|
|
90
|
+
choices = projects.map do |project|
|
|
91
|
+
{ name: project[:name], value: project[:slug] }
|
|
92
|
+
end
|
|
93
|
+
all_choices = choices + [{ name: 'Create a new project', value: nil }]
|
|
94
|
+
answer = Uffizzi.prompt.select(question, all_choices)
|
|
95
|
+
return ConfigFile.write_option(:project, answer) if answer
|
|
96
|
+
|
|
97
|
+
create_new_project(server)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def create_new_project(server)
|
|
101
|
+
project_name = Uffizzi.prompt.ask('Project name: ', required: true)
|
|
102
|
+
generated_slug = Uffizzi::ProjectHelper.generate_slug(project_name)
|
|
103
|
+
project_slug = Uffizzi.prompt.ask('Project slug: ', default: generated_slug)
|
|
104
|
+
raise Uffizzi::Error.new('Slug must not content spaces or special characters') unless project_slug.match?(/^[a-zA-Z0-9\-_]+\Z/i)
|
|
105
|
+
|
|
106
|
+
project_description = Uffizzi.prompt.ask('Project desciption: ')
|
|
107
|
+
|
|
108
|
+
params = {
|
|
109
|
+
project: {
|
|
110
|
+
name: project_name.strip,
|
|
111
|
+
slug: project_slug,
|
|
112
|
+
description: project_description,
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
response = create_project(server, params)
|
|
117
|
+
|
|
118
|
+
if ResponseHelper.created?(response)
|
|
119
|
+
handle_create_project_succeess(response)
|
|
120
|
+
else
|
|
121
|
+
handle_create_project_failed(response)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def handle_create_project_failed(response)
|
|
126
|
+
name_error = response[:body][:errors][:name].first
|
|
127
|
+
name_already_exists = name_error && name_error.first == 'Name already exists'
|
|
128
|
+
message = "Project with name #{project_name} already exists. " \
|
|
129
|
+
'Please run $ uffizzi config to set it as a default project'
|
|
130
|
+
raise Uffizzi::Error.new(message) if name_already_exists
|
|
131
|
+
|
|
132
|
+
ResponseHelper.handle_failed_response(response)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def handle_create_project_succeess(response)
|
|
136
|
+
project = response[:body][:project]
|
|
137
|
+
|
|
138
|
+
ConfigFile.write_option(:project, project[:slug])
|
|
139
|
+
|
|
140
|
+
Uffizzi.ui.say("Project #{project[:name]} was successfully created")
|
|
141
|
+
end
|
|
68
142
|
end
|
|
69
143
|
end
|
data/lib/uffizzi/cli/logout.rb
CHANGED
data/lib/uffizzi/cli/preview.rb
CHANGED
|
@@ -23,7 +23,7 @@ module Uffizzi
|
|
|
23
23
|
run('create', file_path: file_path)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
desc 'uffizzi preview update [DEPLOYMENT_ID] [COMPOSE_FILE]', '
|
|
26
|
+
desc 'uffizzi preview update [DEPLOYMENT_ID] [COMPOSE_FILE]', 'Update a preview'
|
|
27
27
|
method_option :output, required: false, type: :string, aliases: '-o', enum: ['json', 'github-action']
|
|
28
28
|
def update(deployment_name, file_path)
|
|
29
29
|
run('update', deployment_name: deployment_name, file_path: file_path)
|
|
@@ -86,33 +86,42 @@ module Uffizzi
|
|
|
86
86
|
params = file_path.nil? ? {} : prepare_params(file_path)
|
|
87
87
|
response = create_deployment(ConfigFile.read_option(:server), project_slug, params)
|
|
88
88
|
|
|
89
|
-
if ResponseHelper.created?(response)
|
|
90
|
-
deployment = response[:body][:deployment]
|
|
91
|
-
success_message = "Preview created with name deployment-#{deployment[:id]}"
|
|
92
|
-
PreviewService.start_deploy_containers(project_slug, deployment, success_message)
|
|
93
|
-
else
|
|
89
|
+
if !ResponseHelper.created?(response)
|
|
94
90
|
ResponseHelper.handle_failed_response(response)
|
|
95
91
|
end
|
|
92
|
+
|
|
93
|
+
deployment = response[:body][:deployment]
|
|
94
|
+
Uffizzi.ui.say("Preview created with name deployment-#{deployment[:id]}")
|
|
95
|
+
|
|
96
|
+
success = PreviewService.run_containers_deploy(project_slug, deployment)
|
|
97
|
+
|
|
98
|
+
display_deployment_data(deployment, success)
|
|
96
99
|
rescue SystemExit, Interrupt, SocketError
|
|
97
100
|
deployment_id = response[:body][:deployment][:id]
|
|
98
|
-
handle_preview_interruption(deployment_id,
|
|
101
|
+
handle_preview_interruption(deployment_id, ConfigFile.read_option(:server), project_slug)
|
|
99
102
|
end
|
|
100
103
|
|
|
101
104
|
def handle_update_command(deployment_name, file_path, project_slug)
|
|
102
105
|
deployment_id = PreviewService.read_deployment_id(deployment_name)
|
|
103
106
|
|
|
104
|
-
|
|
107
|
+
raise Uffizzi::Error.new("Preview should be specified in 'deployment-PREVIEW_ID' format") if deployment_id.nil?
|
|
105
108
|
|
|
106
109
|
params = prepare_params(file_path)
|
|
107
110
|
response = update_deployment(ConfigFile.read_option(:server), project_slug, deployment_id, params)
|
|
108
111
|
|
|
109
|
-
if ResponseHelper.ok?(response)
|
|
110
|
-
deployment = response[:body][:deployment]
|
|
111
|
-
success_message = "Preview with ID deployment-#{deployment_id} was successfully updated."
|
|
112
|
-
PreviewService.start_deploy_containers(project_slug, deployment, success_message)
|
|
113
|
-
else
|
|
112
|
+
if !ResponseHelper.ok?(response)
|
|
114
113
|
ResponseHelper.handle_failed_response(response)
|
|
115
114
|
end
|
|
115
|
+
|
|
116
|
+
deployment = response[:body][:deployment]
|
|
117
|
+
Uffizzi.ui.say("Preview with ID deployment-#{deployment_id} was successfully updated.")
|
|
118
|
+
|
|
119
|
+
success = PreviewService.run_containers_deploy(project_slug, deployment)
|
|
120
|
+
|
|
121
|
+
display_deployment_data(deployment, success)
|
|
122
|
+
rescue SystemExit, Interrupt, SocketError
|
|
123
|
+
deployment_id = response[:body][:deployment][:id]
|
|
124
|
+
handle_preview_interruption(deployment_id, ConfigFile.read_option(:server), project_slug)
|
|
116
125
|
end
|
|
117
126
|
|
|
118
127
|
def handle_events_command(deployment_name, project_slug)
|
|
@@ -198,7 +207,7 @@ module Uffizzi
|
|
|
198
207
|
|
|
199
208
|
def prepare_params(file_path)
|
|
200
209
|
begin
|
|
201
|
-
compose_file_data = File.read(file_path)
|
|
210
|
+
compose_file_data = EnvVariablesService.substitute_env_variables(File.read(file_path))
|
|
202
211
|
rescue Errno::ENOENT => e
|
|
203
212
|
raise Uffizzi::Error.new(e.message)
|
|
204
213
|
end
|
|
@@ -218,8 +227,8 @@ module Uffizzi
|
|
|
218
227
|
}
|
|
219
228
|
end
|
|
220
229
|
|
|
221
|
-
def handle_preview_interruption(deployment_id,
|
|
222
|
-
deletion_response = delete_deployment(
|
|
230
|
+
def handle_preview_interruption(deployment_id, server, project_slug)
|
|
231
|
+
deletion_response = delete_deployment(server, project_slug, deployment_id)
|
|
223
232
|
deployment_name = "deployment-#{deployment_id}"
|
|
224
233
|
preview_deletion_message = if ResponseHelper.no_content?(deletion_response)
|
|
225
234
|
"The preview #{deployment_name} has been disabled."
|
|
@@ -229,5 +238,23 @@ module Uffizzi
|
|
|
229
238
|
|
|
230
239
|
raise Uffizzi::Error.new("The preview creation was interrupted. #{preview_deletion_message}")
|
|
231
240
|
end
|
|
241
|
+
|
|
242
|
+
def display_deployment_data(deployment, success)
|
|
243
|
+
if Uffizzi.ui.output_format.nil?
|
|
244
|
+
Uffizzi.ui.say('Done')
|
|
245
|
+
preview_url = "https://#{deployment[:preview_url]}"
|
|
246
|
+
Uffizzi.ui.say(preview_url) if success
|
|
247
|
+
else
|
|
248
|
+
deployment_data = build_deployment_data(deployment)
|
|
249
|
+
Uffizzi.ui.output(deployment_data)
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def build_deployment_data(deployment)
|
|
254
|
+
{
|
|
255
|
+
id: "deployment-#{deployment[:id]}",
|
|
256
|
+
url: "https://#{deployment[:preview_url]}",
|
|
257
|
+
}
|
|
258
|
+
end
|
|
232
259
|
end
|
|
233
260
|
end
|
data/lib/uffizzi/cli/project.rb
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
require 'uffizzi'
|
|
4
4
|
require 'uffizzi/auth_helper'
|
|
5
5
|
require 'uffizzi/response_helper'
|
|
6
|
+
require 'uffizzi/helpers/project_helper'
|
|
7
|
+
require 'uffizzi/services/project_service'
|
|
6
8
|
|
|
7
9
|
module Uffizzi
|
|
8
10
|
class Cli::Project < Thor
|
|
@@ -27,8 +29,27 @@ module Uffizzi
|
|
|
27
29
|
run('set-default', project_slug: project_slug)
|
|
28
30
|
end
|
|
29
31
|
|
|
32
|
+
desc 'describe [PROJECT_SLUG]', 'describe'
|
|
33
|
+
method_option :output, type: :string, aliases: '-o', enum: ['json', 'pretty'], default: 'json'
|
|
34
|
+
def describe(project_slug)
|
|
35
|
+
run('describe', project_slug: project_slug)
|
|
36
|
+
end
|
|
37
|
+
|
|
30
38
|
map('set-default' => :set_default)
|
|
31
39
|
|
|
40
|
+
method_option :name, required: true
|
|
41
|
+
method_option :slug, default: ''
|
|
42
|
+
method_option :description, required: false
|
|
43
|
+
desc 'create', 'Create a project'
|
|
44
|
+
def create
|
|
45
|
+
run('create')
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
desc 'delete [PROJECT_SLUG]', 'Delete a project'
|
|
49
|
+
def delete(project_slug)
|
|
50
|
+
run('delete', project_slug: project_slug)
|
|
51
|
+
end
|
|
52
|
+
|
|
32
53
|
private
|
|
33
54
|
|
|
34
55
|
def run(command, project_slug: nil)
|
|
@@ -39,21 +60,74 @@ module Uffizzi
|
|
|
39
60
|
handle_list_command
|
|
40
61
|
when 'set-default'
|
|
41
62
|
handle_set_default_command(project_slug)
|
|
63
|
+
when 'create'
|
|
64
|
+
handle_create_command
|
|
65
|
+
when 'delete'
|
|
66
|
+
handle_delete_command(project_slug)
|
|
67
|
+
when 'describe'
|
|
68
|
+
handle_describe_command(project_slug)
|
|
42
69
|
end
|
|
43
70
|
end
|
|
44
71
|
|
|
72
|
+
def handle_describe_command(project_slug)
|
|
73
|
+
response = describe_project(ConfigFile.read_option(:server), project_slug)
|
|
74
|
+
|
|
75
|
+
if ResponseHelper.ok?(response)
|
|
76
|
+
handle_succeed_describe_response(response)
|
|
77
|
+
else
|
|
78
|
+
ResponseHelper.handle_failed_response(response)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def handle_succeed_describe_response(response)
|
|
83
|
+
project = response[:body][:project]
|
|
84
|
+
project[:deployments] = ProjectService.select_active_deployments(project)
|
|
85
|
+
ProjectService.describe_project(project, options[:output])
|
|
86
|
+
end
|
|
87
|
+
|
|
45
88
|
def handle_list_command
|
|
46
89
|
server = ConfigFile.read_option(:server)
|
|
47
90
|
response = fetch_projects(server)
|
|
48
91
|
|
|
49
92
|
if ResponseHelper.ok?(response)
|
|
50
|
-
|
|
93
|
+
handle_list_success_response(response)
|
|
51
94
|
else
|
|
52
95
|
ResponseHelper.handle_failed_response(response)
|
|
53
96
|
end
|
|
54
97
|
end
|
|
55
98
|
|
|
56
|
-
def
|
|
99
|
+
def handle_create_command
|
|
100
|
+
name = options[:name]
|
|
101
|
+
slug = options[:slug].empty? ? Uffizzi::ProjectHelper.generate_slug(name) : options[:slug]
|
|
102
|
+
raise Uffizzi::Error.new('Slug must not content spaces or special characters') unless slug.match?(/^[a-zA-Z0-9\-_]+\Z/i)
|
|
103
|
+
|
|
104
|
+
server = ConfigFile.read_option(:server)
|
|
105
|
+
params = {
|
|
106
|
+
name: name,
|
|
107
|
+
description: options[:description],
|
|
108
|
+
slug: slug,
|
|
109
|
+
}
|
|
110
|
+
response = create_project(server, params)
|
|
111
|
+
|
|
112
|
+
if ResponseHelper.created?(response)
|
|
113
|
+
handle_create_success_response(response)
|
|
114
|
+
else
|
|
115
|
+
ResponseHelper.handle_failed_response(response)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def handle_delete_command(project_slug)
|
|
120
|
+
server = ConfigFile.read_option(:server)
|
|
121
|
+
response = delete_project(server, project_slug)
|
|
122
|
+
|
|
123
|
+
if ResponseHelper.no_content?(response)
|
|
124
|
+
Uffizzi.ui.say("Project with slug #{project_slug} was deleted successfully")
|
|
125
|
+
else
|
|
126
|
+
ResponseHelper.handle_failed_response(response)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def handle_list_success_response(response)
|
|
57
131
|
projects = response[:body][:projects]
|
|
58
132
|
return Uffizzi.ui.say('No projects related to this email') if projects.empty?
|
|
59
133
|
|
|
@@ -76,6 +150,12 @@ module Uffizzi
|
|
|
76
150
|
Uffizzi.ui.say('Default project has been updated.')
|
|
77
151
|
end
|
|
78
152
|
|
|
153
|
+
def handle_create_success_response(response)
|
|
154
|
+
project_name = response[:body][:project][:name]
|
|
155
|
+
|
|
156
|
+
Uffizzi.ui.say("Project #{project_name} was successfully created")
|
|
157
|
+
end
|
|
158
|
+
|
|
79
159
|
def print_projects(projects)
|
|
80
160
|
projects_list = projects.reduce('') do |acc, project|
|
|
81
161
|
"#{acc}#{project[:slug]}\n"
|
data/lib/uffizzi/cli.rb
CHANGED
|
@@ -62,8 +62,10 @@ module Uffizzi
|
|
|
62
62
|
return Common.show_manual(filename(args)) if show_help?(args, opts)
|
|
63
63
|
|
|
64
64
|
super
|
|
65
|
-
rescue
|
|
65
|
+
rescue Interrupt
|
|
66
66
|
raise Uffizzi::Error.new('The command was interrupted')
|
|
67
|
+
rescue SocketError
|
|
68
|
+
raise Uffizzi::Error.new('A request was not sent to Uffizzi app')
|
|
67
69
|
end
|
|
68
70
|
|
|
69
71
|
private
|
|
@@ -49,6 +49,20 @@ module ApiClient
|
|
|
49
49
|
build_response(response)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
def create_project(server, params)
|
|
53
|
+
uri = projects_uri(server)
|
|
54
|
+
response = http_client.make_post_request(uri, params)
|
|
55
|
+
|
|
56
|
+
build_response(response)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def delete_project(server, project_slug)
|
|
60
|
+
uri = project_uri(server, project_slug)
|
|
61
|
+
response = http_client.make_delete_request(uri)
|
|
62
|
+
|
|
63
|
+
build_response(response)
|
|
64
|
+
end
|
|
65
|
+
|
|
52
66
|
def create_credential(server, params)
|
|
53
67
|
uri = credentials_uri(server)
|
|
54
68
|
response = http_client.make_post_request(uri, params)
|
|
@@ -221,7 +235,7 @@ module ApiClient
|
|
|
221
235
|
|
|
222
236
|
cookie_content = cookies.first
|
|
223
237
|
cookie = cookie_content.split(';').first
|
|
224
|
-
Uffizzi::ConfigFile.rewrite_cookie(cookie) if Uffizzi::ConfigFile.exists?
|
|
238
|
+
Uffizzi::ConfigFile.rewrite_cookie(cookie) if Uffizzi::ConfigFile.exists? && Uffizzi::ConfigFile.option_has_value?(:cookie)
|
|
225
239
|
http_client.auth_cookie = cookie
|
|
226
240
|
|
|
227
241
|
cookie
|