uffizzi_core 0.1.13 → 0.1.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/app/clients/uffizzi_core/docker_hub_client/not_authorized_error.rb +6 -0
  3. data/app/controllers/concerns/uffizzi_core/dependency_injection_concern.rb +6 -0
  4. data/app/controllers/uffizzi_core/api/cli/v1/projects_controller.rb +57 -2
  5. data/app/forms/uffizzi_core/api/cli/v1/deployment/update_form.rb +1 -1
  6. data/app/forms/uffizzi_core/api/cli/v1/project/create_form.rb +7 -0
  7. data/app/lib/uffizzi_core/rbac/user_access_service.rb +4 -0
  8. data/app/models/uffizzi_core/project.rb +9 -2
  9. data/app/policies/uffizzi_core/api/cli/v1/projects_policy.rb +12 -0
  10. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer/compose_file_serializer.rb +7 -0
  11. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer/deployment_serializer.rb +13 -0
  12. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer.rb +28 -1
  13. data/app/serializers/uffizzi_core/api/cli/v1/short_project_serializer.rb +7 -0
  14. data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer/container_config_file_serializer/config_file_serializer.rb +2 -2
  15. data/app/services/uffizzi_core/compose_file/services_options_service.rb +10 -2
  16. data/app/services/uffizzi_core/deployment_service.rb +6 -15
  17. data/app/services/uffizzi_core/manage_activity_items_service.rb +0 -8
  18. data/app/services/uffizzi_core/project_service.rb +10 -0
  19. data/app/services/uffizzi_core/user_generator_service.rb +11 -5
  20. data/config/routes.rb +1 -1
  21. data/lib/tasks/uffizzi_core_tasks.rake +1 -1
  22. data/lib/uffizzi_core/version.rb +1 -1
  23. data/swagger/v1/swagger.json +173 -1
  24. metadata +7 -5
  25. data/app/lib/uffizzi_core/concerns/models/activity_item.rb +0 -39
  26. data/app/lib/uffizzi_core/concerns/models/credential.rb +0 -65
  27. data/app/lib/uffizzi_core/concerns/models/repo.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d892c859a5a90f309d59a2fd110e3e99719d62f566cda4f7cb1f0815c700f4e
4
- data.tar.gz: df8bed87726cc99d3401b129245a8bc0467d087550d3258f66f08c482f897f7e
3
+ metadata.gz: cfa4de16cbd2efbc1c9b12748807a9c283e206a490eaa4cf544eaee9e5a11733
4
+ data.tar.gz: 8d3d6a27ed932c3760669f2397deef476b57c44ec09b783de51eca3143bb7aad
5
5
  SHA512:
6
- metadata.gz: dc59d9a62a34892c5c50eb0b622e7a5e46ecd0e0cdbd826ea72fd0b27c88dc35ddd7c686b3b46b1aa16c2544374f5f96ca4588d41afb39433b8759fabba8484e
7
- data.tar.gz: 070f387c4d12a5d662c392dfa715dd536d8100aa06978c072dbaee04bec52dd9aa126b396903610dbfc187dbac5542d7c7332d1b5a7df784210b21c1a31cea20
6
+ metadata.gz: 0db9e7b5f79bf19ac9576b516e72792b3a58ff98edccea36ef1f9a4385e214d7498d5c5dc047fb989cd1c958a8ec8be32ad39d0257ab57c8b264a6fef7b85d96
7
+ data.tar.gz: a1f4c8f5a39e04357a1e9185454230b7671dffdac46f180a23310ae07f0b906912cf10fcd252fdfd1d31c7553a3074d139d504d94a916f4b2219e174771be945
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::DockerHubClient
4
+ class NotAuthorizedError < StandardError
5
+ end
6
+ end
@@ -7,6 +7,12 @@ module UffizziCore::DependencyInjectionConcern
7
7
  UffizziCore::UserAccessService.new(module_class(:rbac))
8
8
  end
9
9
 
10
+ def build_parser_module
11
+ return unless module_exists?(:github)
12
+
13
+ module_class(:github).new
14
+ end
15
+
10
16
  private
11
17
 
12
18
  def module_exists?(module_name)
@@ -9,11 +9,66 @@ class UffizziCore::Api::Cli::V1::ProjectsController < UffizziCore::Api::Cli::V1:
9
9
  #
10
10
  # @path [GET] /api/cli/v1/projects
11
11
  #
12
- # @response [object<projects: Array<object<slug: string>> >] 200 OK
12
+ # @response [object<projects: Array<object<slug: string, name: string>> >] 200 OK
13
13
  # @response 401 Not authorized
14
14
  def index
15
15
  projects = current_user.projects.active.order(updated_at: :desc)
16
16
 
17
- respond_with projects
17
+ respond_with projects, each_serializer: UffizziCore::Api::Cli::V1::ShortProjectSerializer
18
+ end
19
+
20
+ # Get a project by slug
21
+ #
22
+ # @path [GET] /api/cli/v1/projects/{slug}
23
+ #
24
+ # @response <object< project: Project>> 200 OK
25
+ # @response 404 Not Found
26
+ # @response 401 Not authorized
27
+ def show
28
+ project = current_user.projects.find_by!(slug: params[:slug])
29
+
30
+ respond_with project
31
+ end
32
+
33
+ # Create a project
34
+ #
35
+ # @path [POST] /api/cli/v1/projects
36
+ # @parameter params(required,body) [object<name: string, slug: string, description: string>]
37
+ #
38
+ # @response <object< project: Project>> 200 OK
39
+ # @response 404 Not Found
40
+ # @response 401 Not authorized
41
+ # @response [object<errors: object<password: string >>] 422 Unprocessable entity
42
+
43
+ def create
44
+ project_form = UffizziCore::Api::Cli::V1::Project::CreateForm.new(project_params)
45
+ project_form.account = current_user.organizational_account
46
+
47
+ if project_form.save
48
+ UffizziCore::ProjectService.add_users_to_project!(project_form, current_user)
49
+ end
50
+
51
+ respond_with project_form
52
+ end
53
+
54
+ # Delete a project
55
+ #
56
+ # @path [DELETE] /api/cli/v1/projects/{slug}
57
+ #
58
+ # @response 204 No content
59
+ # @response 404 Not Found
60
+ # @response 401 Not authorized
61
+
62
+ def destroy
63
+ project = current_user.organizational_account.active_projects.find_by!(slug: params[:slug])
64
+ project.disable!
65
+
66
+ head :no_content
67
+ end
68
+
69
+ private
70
+
71
+ def project_params
72
+ params.require(:project)
18
73
  end
19
74
  end
@@ -5,7 +5,7 @@ class UffizziCore::Api::Cli::V1::Deployment::UpdateForm < UffizziCore::Deploymen
5
5
 
6
6
  permit containers_attributes: [
7
7
  :image,
8
- :name,
8
+ :service_name,
9
9
  :tag,
10
10
  :port,
11
11
  :public,
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::Project::CreateForm < UffizziCore::Project
4
+ include UffizziCore::ApplicationForm
5
+
6
+ permit :name, :slug, :description
7
+ end
@@ -10,6 +10,10 @@ module UffizziCore::Rbac::UserAccessService
10
10
  true
11
11
  end
12
12
 
13
+ def admin_or_developer_access_to_account?(_user, _account)
14
+ true
15
+ end
16
+
13
17
  def admin_or_developer_access_to_project?(_user, _project)
14
18
  true
15
19
  end
@@ -1,7 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # @model
3
+ # @model Project
4
4
  # @property slug [string]
5
+ # @property name [string]
6
+ # @property description [string]
7
+ # @property created_at [date-time]
8
+ # @property secrets [string]
9
+ # @property default_compose [object<source: string>]
10
+ # @property deployments [object<id: integer, domain: string>]
5
11
 
6
12
  class UffizziCore::Project < UffizziCore::ApplicationRecord
7
13
  include AASM
@@ -23,7 +29,8 @@ class UffizziCore::Project < UffizziCore::ApplicationRecord
23
29
  has_many :compose_files, dependent: :destroy
24
30
  has_many :secrets, dependent: :destroy, as: :resource
25
31
 
26
- validates :name, presence: true, uniqueness: { scope: :account }
32
+ validates :name, presence: true, uniqueness: { scope: :account, message: 'Name already exists' }
33
+ validates :slug, presence: true, uniqueness: { message: 'Project slug already taken' }
27
34
 
28
35
  aasm(:state) do
29
36
  state :active, initial: true
@@ -4,4 +4,16 @@ class UffizziCore::Api::Cli::V1::ProjectsPolicy < UffizziCore::ApplicationPolicy
4
4
  def index?
5
5
  context.user_access_module.any_access_to_account?(context.user, context.account)
6
6
  end
7
+
8
+ def show?
9
+ context.user_access_module.any_access_to_account?(context.user, context.account)
10
+ end
11
+
12
+ def create?
13
+ context.user_access_module.admin_or_developer_access_to_account?(context.user, context.account)
14
+ end
15
+
16
+ def destroy?
17
+ context.user_access_module.admin_or_developer_access_to_account?(context.user, context.account)
18
+ end
7
19
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ProjectSerializer::ComposeFileSerializer < UffizziCore::BaseSerializer
4
+ type :compose_file
5
+
6
+ attributes :source
7
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ProjectSerializer::DeploymentSerializer < UffizziCore::BaseSerializer
4
+ type :deployment
5
+
6
+ attributes :id,
7
+ :preview_url,
8
+ :state
9
+
10
+ def preview_url
11
+ UffizziCore::DeploymentService.build_preview_url(object)
12
+ end
13
+ end
@@ -2,6 +2,33 @@
2
2
 
3
3
  class UffizziCore::Api::Cli::V1::ProjectSerializer < UffizziCore::BaseSerializer
4
4
  type :project
5
+ has_many :deployments
6
+ has_many :secrets
7
+ has_one :default_compose
5
8
 
6
- attributes :slug
9
+ attributes :name,
10
+ :slug,
11
+ :description,
12
+ :created_at
13
+
14
+ def default_compose
15
+ object.compose_files.main.first
16
+ end
17
+
18
+ def deployments
19
+ object.deployments.active.map do |deployment|
20
+ deployment.state = if UffizziCore::DeploymentService.failed?(deployment)
21
+ UffizziCore::Deployment::STATE_FAILED
22
+ else
23
+ UffizziCore::Deployment::STATE_ACTIVE
24
+ end
25
+ deployment
26
+ end
27
+ end
28
+
29
+ def secrets
30
+ return [] unless object.secrets
31
+
32
+ object.secrets.map(&:name)
33
+ end
7
34
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ShortProjectSerializer < UffizziCore::BaseSerializer
4
+ type :project
5
+
6
+ attributes :name, :slug
7
+ end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rubocop:disable Metrics/LineLength
3
+ # rubocop:disable Layout/LineLength
4
4
  class UffizziCore::Controller::DeployContainers::ContainerSerializer::ContainerConfigFileSerializer::ConfigFileSerializer < UffizziCore::BaseSerializer
5
- # rubocop:enable Metrics/LineLength
5
+ # rubocop:enable Layout/LineLength
6
6
 
7
7
  attributes :id, :filename, :kind, :payload
8
8
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  class UffizziCore::ComposeFile::ServicesOptionsService
4
4
  class << self
5
+ include UffizziCore::DependencyInjectionConcern
6
+
5
7
  def parse(services, global_configs_data, global_secrets_data, compose_payload)
6
8
  raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.no_services') if services.nil? || services.keys.empty?
7
9
 
@@ -18,7 +20,7 @@ class UffizziCore::ComposeFile::ServicesOptionsService
18
20
 
19
21
  private
20
22
 
21
- def prepare_service_data(service_name, service_data, global_configs_data, global_secrets_data, _compose_payload)
23
+ def prepare_service_data(service_name, service_data, global_configs_data, global_secrets_data, compose_payload)
22
24
  options_data = {}
23
25
  service_data.each_pair do |key, value|
24
26
  service_key = key.to_sym
@@ -27,7 +29,7 @@ class UffizziCore::ComposeFile::ServicesOptionsService
27
29
  when :image
28
30
  UffizziCore::ComposeFile::ServicesOptions::ImageService.parse(value)
29
31
  when :build
30
- raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.not_implemented', option: :build)
32
+ check_and_parse_build_option(value, compose_payload)
31
33
  when :env_file
32
34
  UffizziCore::ComposeFile::ServicesOptions::EnvFileService.parse(value)
33
35
  when :environment
@@ -51,5 +53,11 @@ class UffizziCore::ComposeFile::ServicesOptionsService
51
53
 
52
54
  options_data
53
55
  end
56
+
57
+ def check_and_parse_build_option(value, compose_payload)
58
+ raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.not_implemented', option: :build) unless build_parser_module
59
+
60
+ build_parser_module.parse(value, compose_payload)
61
+ end
54
62
  end
55
63
  end
@@ -8,6 +8,7 @@ module UffizziCore::DeploymentService
8
8
  building: :building,
9
9
  deploying: :deploying,
10
10
  failed: :failed,
11
+ queued: :queued,
11
12
  }.freeze
12
13
 
13
14
  class << self
@@ -103,9 +104,8 @@ module UffizziCore::DeploymentService
103
104
  pull_request_payload = continuous_preview_payload['pull_request']
104
105
  repo_name = pull_request_payload['repository_full_name'].split('/').last
105
106
  deployment_name = name(deployment)
106
- subdomain = "pr#{pull_request_payload['id']}-#{deployment_name}-#{repo_name}-#{project.slug}"
107
107
 
108
- format_subdomain(subdomain)
108
+ "pr#{pull_request_payload['id']}-#{deployment_name}.#{repo_name}.#{project.slug}"
109
109
  end
110
110
 
111
111
  def build_docker_continuous_preview_subdomain(deployment)
@@ -115,17 +115,14 @@ module UffizziCore::DeploymentService
115
115
  repo_name = docker_payload['image'].split('/').last.gsub('_', '-')
116
116
  image_tag = docker_payload['tag'].gsub('_', '-')
117
117
  deployment_name = name(deployment)
118
- subdomain = "#{image_tag}-#{deployment_name}-#{repo_name}-#{project.slug}"
119
118
 
120
- format_subdomain(subdomain)
119
+ "#{image_tag}-#{deployment_name}.#{repo_name}.#{project.slug}"
121
120
  end
122
121
 
123
122
  def build_default_subdomain(deployment)
124
123
  deployment_name = name(deployment)
125
124
  slug = deployment.project.slug.to_s
126
- subdomain = "#{deployment_name}-#{slug}"
127
-
128
- format_subdomain(subdomain)
125
+ "#{deployment_name}.#{slug}"
129
126
  end
130
127
 
131
128
  def build_preview_url(deployment)
@@ -242,10 +239,11 @@ module UffizziCore::DeploymentService
242
239
 
243
240
  def deployment_process_status(deployment)
244
241
  containers = deployment.active_containers
245
- activity_items = containers.map { |container| container.activity_items.order_by_id.last }
242
+ activity_items = containers.map { |container| container.activity_items.order_by_id.last }.compact
246
243
  events = activity_items.map { |activity_item| activity_item.events.order_by_id.last&.state }
247
244
  events = events.flatten.uniq
248
245
 
246
+ return DEPLOYMENT_PROCESS_STATUSES[:queued] if events.empty?
249
247
  return DEPLOYMENT_PROCESS_STATUSES[:failed] if events.include?(UffizziCore::Event.state.failed)
250
248
  return DEPLOYMENT_PROCESS_STATUSES[:building] if events.include?(UffizziCore::Event.state.building)
251
249
 
@@ -295,12 +293,5 @@ module UffizziCore::DeploymentService
295
293
  container.variables.push(*envs)
296
294
  end
297
295
  end
298
-
299
- def format_subdomain(full_subdomain_name)
300
- subdomain_length_limit = Settings.deployment.subdomain.length_limit
301
- return full_subdomain_name if full_subdomain_name.length <= subdomain_length_limit
302
-
303
- full_subdomain_name.slice(0, subdomain_length_limit)
304
- end
305
296
  end
306
297
  end
@@ -116,26 +116,18 @@ class UffizziCore::ManageActivityItemsService
116
116
  state = pod_container[:state][pod_container_status]
117
117
  reason = state&.reason
118
118
 
119
- Rails.logger.info("manage_activity_items get_status dep_id=#{container.deployment.id} pod_container_status: #{pod_container_status}")
120
- Rails.logger.info("manage_activity_items get_status dep_id=#{container.deployment.id} state: #{state}")
121
- ap pod_container[:state]
122
-
123
119
  case pod_container_status.to_sym
124
120
  when :running
125
- Rails.logger.info("manage_activity_items get_status dep_id=#{container.deployment.id} running")
126
121
  UffizziCore::Event.state.deployed
127
122
  when :terminated
128
- Rails.logger.info("manage_activity_items get_status dep_id=#{container.deployment.id} terminated")
129
123
  UffizziCore::Event.state.failed
130
124
  when :waiting
131
- Rails.logger.info("manage_activity_items get_status dep_id=#{container.deployment.id} waiting")
132
125
  return UffizziCore::Event.state.failed if ['CrashLoopBackOff'].include?(reason)
133
126
 
134
127
  raise UffizziCore::Deployment::ImagePullError, @deployment.id if ['ErrImagePull', 'ImagePullBackOff'].include?(reason)
135
128
 
136
129
  UffizziCore::Event.state.deploying
137
130
  else
138
- Rails.logger.info("manage_activity_items get_status dep_id=#{container.deployment.id} else")
139
131
  UffizziCore::Event.state.deploying
140
132
  end
141
133
  end
@@ -34,5 +34,15 @@ module UffizziCore::ProjectService
34
34
 
35
35
  UffizziCore::ComposeFile::ErrorsService.update_compose_errors!(compose_file, new_errors, compose_file.content)
36
36
  end
37
+
38
+ def add_users_to_project!(project, current_user)
39
+ user_projects = []
40
+
41
+ current_user.organizational_account.memberships.where(role: UffizziCore::Membership.role.admin).map do |membership|
42
+ user_projects << { project: project, user: membership.user, role: UffizziCore::UserProject.role.admin }
43
+ end
44
+
45
+ UffizziCore::UserProject.create!(user_projects)
46
+ end
37
47
  end
38
48
  end
@@ -6,6 +6,12 @@ class UffizziCore::UserGeneratorService
6
6
  DEFAULT_ACCOUNT_NAME = 'default'
7
7
 
8
8
  class << self
9
+ def safe_generate(email, password, project_name)
10
+ generate(email, password, project_name)
11
+ rescue ActiveRecord::RecordInvalid => e
12
+ puts e.message
13
+ end
14
+
9
15
  def generate(email, password, project_name)
10
16
  user_attributes = build_user_attributes(email, password)
11
17
  project_attributes = build_project_attributes(project_name)
@@ -31,19 +37,17 @@ class UffizziCore::UserGeneratorService
31
37
 
32
38
  if email.present?
33
39
  user_attributes[:email] = email
34
- else
40
+ elsif IO::console.present?
35
41
  IO::console.write("Enter User Email (default: #{DEFAULT_USER_EMAIL}): ")
36
42
  user_attributes[:email] = IO::console.gets.strip.presence || DEFAULT_USER_EMAIL
37
43
  end
38
44
 
39
45
  user_attributes[:password] = if password.present?
40
46
  password
41
- else
47
+ elsif IO::console.present?
42
48
  IO::console.getpass('Enter Password: ')
43
49
  end
44
50
 
45
- abort('password can\'t be blank') if user_attributes[:password].blank?
46
-
47
51
  user_attributes
48
52
  end
49
53
 
@@ -53,9 +57,11 @@ class UffizziCore::UserGeneratorService
53
57
  }
54
58
  if project_name.present?
55
59
  project_attributes[:name] = project_name
56
- else
60
+ elsif IO::console.present?
57
61
  IO::console.write("Enter Project Name (default: #{DEFAULT_PROJECT_NAME}): ")
58
62
  project_attributes[:name] = IO::console.gets.strip.presence || DEFAULT_PROJECT_NAME
63
+ else
64
+ project_attributes[:name] = DEFAULT_PROJECT_NAME
59
65
  end
60
66
 
61
67
  project_attributes[:slug] = prepare_project_slug(project_attributes[:name])
data/config/routes.rb CHANGED
@@ -15,7 +15,7 @@ UffizziCore::Engine.routes.draw do
15
15
  post :google
16
16
  end
17
17
 
18
- resources :projects, only: ['index'], param: :slug do
18
+ resources :projects, only: ['index', 'show', 'create', 'destroy'], param: :slug do
19
19
  scope module: :projects do
20
20
  resource :compose_file, only: ['show', 'create', 'destroy']
21
21
  resources :deployments, only: ['index', 'show', 'create', 'destroy', 'update'] do
@@ -14,6 +14,6 @@ namespace :uffizzi_core do
14
14
 
15
15
  desc 'Create a new user'
16
16
  task create_user: :environment do
17
- UffizziCore::UserGeneratorService.generate(ENV['UFFIZZI_USER_EMAIL'], ENV['UFFIZZI_USER_PASSWORD'], ENV['UFFIZZI_PROJECT_NAME'])
17
+ UffizziCore::UserGeneratorService.safe_generate(ENV['UFFIZZI_USER_EMAIL'], ENV['UFFIZZI_USER_PASSWORD'], ENV['UFFIZZI_PROJECT_NAME'])
18
18
  end
19
19
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module UffizziCore
4
- VERSION = '0.1.13'
4
+ VERSION = '0.1.16'
5
5
  end
@@ -1134,6 +1134,9 @@
1134
1134
  "properties": {
1135
1135
  "slug": {
1136
1136
  "type": "string"
1137
+ },
1138
+ "name": {
1139
+ "type": "string"
1137
1140
  }
1138
1141
  }
1139
1142
  }
@@ -1149,6 +1152,143 @@
1149
1152
  "summary": "Get projects of current user",
1150
1153
  "x-controller": "uffizzi_core/api/cli/v1/projects",
1151
1154
  "x-action": "index"
1155
+ },
1156
+ "post": {
1157
+ "tags": [
1158
+ "Project"
1159
+ ],
1160
+ "operationId": "Project-create",
1161
+ "parameters": [
1162
+ {
1163
+ "name": "params",
1164
+ "description": "params",
1165
+ "required": true,
1166
+ "in": "body",
1167
+ "schema": {
1168
+ "type": "object",
1169
+ "properties": {
1170
+ "name": {
1171
+ "type": "string"
1172
+ },
1173
+ "slug": {
1174
+ "type": "string"
1175
+ },
1176
+ "description": {
1177
+ "type": "string"
1178
+ }
1179
+ }
1180
+ }
1181
+ }
1182
+ ],
1183
+ "responses": {
1184
+ "200": {
1185
+ "description": "OK",
1186
+ "schema": {
1187
+ "type": "object",
1188
+ "properties": {
1189
+ "project": {
1190
+ "$ref": "#/definitions/Project"
1191
+ }
1192
+ }
1193
+ }
1194
+ },
1195
+ "404": {
1196
+ "description": "Not Found"
1197
+ },
1198
+ "401": {
1199
+ "description": "Not authorized"
1200
+ },
1201
+ "422": {
1202
+ "description": "Unprocessable entity",
1203
+ "schema": {
1204
+ "type": "object",
1205
+ "properties": {
1206
+ "errors": {
1207
+ "type": "object",
1208
+ "properties": {
1209
+ "password": {
1210
+ "type": "string"
1211
+ }
1212
+ }
1213
+ }
1214
+ }
1215
+ }
1216
+ }
1217
+ },
1218
+ "description": "Create a project",
1219
+ "summary": "Create a project",
1220
+ "x-controller": "uffizzi_core/api/cli/v1/projects",
1221
+ "x-action": "create"
1222
+ }
1223
+ },
1224
+ "/api/cli/v1/projects/{slug}": {
1225
+ "get": {
1226
+ "tags": [
1227
+ "Project"
1228
+ ],
1229
+ "operationId": "Project-show",
1230
+ "parameters": [
1231
+ {
1232
+ "name": "slug",
1233
+ "description": "Scope response to slug",
1234
+ "required": true,
1235
+ "in": "path",
1236
+ "type": "string"
1237
+ }
1238
+ ],
1239
+ "responses": {
1240
+ "204": {
1241
+ "description": "No content"
1242
+ },
1243
+ "404": {
1244
+ "description": "Not Found"
1245
+ },
1246
+ "401": {
1247
+ "description": "Not authorized"
1248
+ }
1249
+ },
1250
+ "description": "Get a project by slug",
1251
+ "summary": "Get a project by slug",
1252
+ "x-controller": "uffizzi_core/api/cli/v1/projects",
1253
+ "x-action": "show"
1254
+ },
1255
+ "delete": {
1256
+ "tags": [
1257
+ "Project"
1258
+ ],
1259
+ "operationId": "Project-destroy",
1260
+ "parameters": [
1261
+ {
1262
+ "name": "slug",
1263
+ "description": "Scope response to slug",
1264
+ "required": true,
1265
+ "in": "path",
1266
+ "type": "string"
1267
+ }
1268
+ ],
1269
+ "responses": {
1270
+ "200": {
1271
+ "description": "OK",
1272
+ "schema": {
1273
+ "type": "object",
1274
+ "properties": {
1275
+ "project": {
1276
+ "$ref": "#/definitions/Project"
1277
+ }
1278
+ }
1279
+ }
1280
+ },
1281
+ "404": {
1282
+ "description": "Not Found"
1283
+ },
1284
+ "401": {
1285
+ "description": "Not authorized"
1286
+ }
1287
+ },
1288
+ "description": "Delete a project",
1289
+ "summary": "Delete a project",
1290
+ "x-controller": "uffizzi_core/api/cli/v1/projects",
1291
+ "x-action": "destroy"
1152
1292
  }
1153
1293
  },
1154
1294
  "/api/cli/v1/session": {
@@ -1475,11 +1615,43 @@
1475
1615
  }
1476
1616
  }
1477
1617
  },
1478
- "UffizziCore_Project": {
1618
+ "Project": {
1479
1619
  "type": "object",
1480
1620
  "properties": {
1481
1621
  "slug": {
1482
1622
  "type": "string"
1623
+ },
1624
+ "name": {
1625
+ "type": "string"
1626
+ },
1627
+ "description": {
1628
+ "type": "string"
1629
+ },
1630
+ "created_at": {
1631
+ "type": "string",
1632
+ "format": "date-time"
1633
+ },
1634
+ "secrets": {
1635
+ "type": "string"
1636
+ },
1637
+ "default_compose": {
1638
+ "type": "object",
1639
+ "properties": {
1640
+ "source": {
1641
+ "type": "string"
1642
+ }
1643
+ }
1644
+ },
1645
+ "deployments": {
1646
+ "type": "object",
1647
+ "properties": {
1648
+ "id": {
1649
+ "type": "integer"
1650
+ },
1651
+ "domain": {
1652
+ "type": "string"
1653
+ }
1654
+ }
1483
1655
  }
1484
1656
  }
1485
1657
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uffizzi_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ version: 0.1.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Thurman
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-05-30 00:00:00.000000000 Z
12
+ date: 2022-06-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aasm
@@ -693,6 +693,7 @@ files:
693
693
  - app/clients/uffizzi_core/controller_client.rb
694
694
  - app/clients/uffizzi_core/controller_client/request_result.rb
695
695
  - app/clients/uffizzi_core/docker_hub_client.rb
696
+ - app/clients/uffizzi_core/docker_hub_client/not_authorized_error.rb
696
697
  - app/clients/uffizzi_core/docker_hub_client/request_result.rb
697
698
  - app/clients/uffizzi_core/github_container_registry_client.rb
698
699
  - app/clients/uffizzi_core/github_container_registry_client/request_result.rb
@@ -736,6 +737,7 @@ files:
736
737
  - app/forms/uffizzi_core/api/cli/v1/config_file/create_form.rb
737
738
  - app/forms/uffizzi_core/api/cli/v1/deployment/create_form.rb
738
739
  - app/forms/uffizzi_core/api/cli/v1/deployment/update_form.rb
740
+ - app/forms/uffizzi_core/api/cli/v1/project/create_form.rb
739
741
  - app/forms/uffizzi_core/api/cli/v1/project/update_form.rb
740
742
  - app/forms/uffizzi_core/api/cli/v1/secret/bulk_assign_form.rb
741
743
  - app/forms/uffizzi_core/api/cli/v1/session_create_form.rb
@@ -757,9 +759,6 @@ files:
757
759
  - app/jobs/uffizzi_core/deployment/delete_job.rb
758
760
  - app/jobs/uffizzi_core/deployment/deploy_containers_job.rb
759
761
  - app/jobs/uffizzi_core/deployment/manage_deploy_activity_item_job.rb
760
- - app/lib/uffizzi_core/concerns/models/activity_item.rb
761
- - app/lib/uffizzi_core/concerns/models/credential.rb
762
- - app/lib/uffizzi_core/concerns/models/repo.rb
763
762
  - app/lib/uffizzi_core/rbac/user_access_service.rb
764
763
  - app/mailers/uffizzi_core/application_mailer.rb
765
764
  - app/models/concerns/uffizzi_core/hashid_concern.rb
@@ -838,6 +837,8 @@ files:
838
837
  - app/responders/uffizzi_core/json_responder.rb
839
838
  - app/serializers/uffizzi_core/api/cli/v1/account/credential_serializer.rb
840
839
  - app/serializers/uffizzi_core/api/cli/v1/project_serializer.rb
840
+ - app/serializers/uffizzi_core/api/cli/v1/project_serializer/compose_file_serializer.rb
841
+ - app/serializers/uffizzi_core/api/cli/v1/project_serializer/deployment_serializer.rb
841
842
  - app/serializers/uffizzi_core/api/cli/v1/projects/compose_file_serializer.rb
842
843
  - app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer.rb
843
844
  - app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb
@@ -847,6 +848,7 @@ files:
847
848
  - app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer/container_config_file_serializer.rb
848
849
  - app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer/container_config_file_serializer/config_file_serializer.rb
849
850
  - app/serializers/uffizzi_core/api/cli/v1/projects/secret_serializer.rb
851
+ - app/serializers/uffizzi_core/api/cli/v1/short_project_serializer.rb
850
852
  - app/serializers/uffizzi_core/api/cli/v1/user_serializer.rb
851
853
  - app/serializers/uffizzi_core/api/cli/v1/user_serializer/account_serializer.rb
852
854
  - app/serializers/uffizzi_core/base_serializer.rb
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module UffizziCore::Concerns::Models::ActivityItem
4
- extend ActiveSupport::Concern
5
-
6
- included do
7
- include UffizziCore::ActivityItemRepo
8
-
9
- self.table_name = UffizziCore.table_names[:activity_items]
10
-
11
- belongs_to :deployment
12
- belongs_to :container
13
- belongs_to :build, optional: true
14
-
15
- has_many :events, dependent: :destroy
16
-
17
- scope :docker, -> {
18
- where(type: UffizziCore::ActivityItem::Docker.name)
19
- }
20
-
21
- scope :github, -> {
22
- where(type: UffizziCore::ActivityItem::Github.name)
23
- }
24
-
25
- def docker?
26
- type == UffizziCore::ActivityItem::Docker.name
27
- end
28
-
29
- def image
30
- [namespace, name].compact.join('/')
31
- end
32
-
33
- def full_image
34
- return "#{image}:#{tag}" if docker?
35
-
36
- ''
37
- end
38
- end
39
- end
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module UffizziCore::Concerns::Models::Credential
4
- extend ActiveSupport::Concern
5
-
6
- included do
7
- include AASM
8
- include UffizziCore::CredentialRepo
9
-
10
- self.table_name = UffizziCore.table_names[:credentials]
11
-
12
- belongs_to :account
13
-
14
- before_destroy :remove_token
15
-
16
- validates :registry_url, presence: true
17
-
18
- aasm :state, column: :state do
19
- state :not_connected, initial: true
20
- state :active
21
- state :unauthorized
22
-
23
- event :activate do
24
- transitions from: [:not_connected, :unauthorized], to: :active
25
- end
26
-
27
- event :unauthorize do
28
- transitions from: [:not_connected, :active], to: :unauthorized
29
- end
30
- end
31
-
32
- def github_container_registry?
33
- type == UffizziCore::Credential::GithubContainerRegistry.name
34
- end
35
-
36
- def docker_hub?
37
- type == UffizziCore::Credential::DockerHub.name
38
- end
39
-
40
- def azure?
41
- type == UffizziCore::Credential::Azure.name
42
- end
43
-
44
- def google?
45
- type == UffizziCore::Credential::Google.name
46
- end
47
-
48
- def amazon?
49
- type == UffizziCore::Credential::Amazon.name
50
- end
51
-
52
- private
53
-
54
- def remove_token
55
- account.projects.find_each do |project|
56
- project.deployments.find_each do |deployment|
57
- containers = deployment.containers
58
- attributes = { continuously_deploy: UffizziCore::Container::STATE_DISABLED }
59
-
60
- containers.with_docker_hub_repo.update_all(attributes) if docker_hub?
61
- end
62
- end
63
- end
64
- end
65
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module UffizziCore::Concerns::Models::Repo
4
- extend ActiveSupport::Concern
5
-
6
- included do
7
- extend Enumerize
8
- include UffizziCore::RepoRepo
9
-
10
- self.table_name = UffizziCore.table_names[:repos]
11
-
12
- enumerize :kind, in: [:buildpacks18, :dockerfile, :dotnet, :gatsby, :barestatic], predicates: true
13
-
14
- belongs_to :project
15
- has_one :container, inverse_of: :repo, dependent: :destroy
16
- has_many :builds, dependent: :destroy
17
-
18
- validates :dockerfile_path, presence: true, if: :dockerfile?
19
- validates :delete_preview_after, numericality: { greater_than: 0, only_integer: true }, allow_nil: true
20
-
21
- def docker_hub?
22
- type == UffizziCore::Repo::DockerHub.name
23
- end
24
-
25
- def azure?
26
- type == UffizziCore::Repo::Azure.name
27
- end
28
-
29
- def google?
30
- type == UffizziCore::Repo::Google.name
31
- end
32
- end
33
- end