Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-11-13 09:06:38 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2019-11-13 09:06:38 +0300
commit213ce7805856f2cc1d019a03c76ae0d098337c26 (patch)
treee97e9e02515dd83a2a5decd66ae8553ebb93b350 /app
parentd41c040fa25a8b4092843b84bf7d839591b6ee09 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/controllers/clusters/clusters_controller.rb54
-rw-r--r--app/helpers/clusters_helper.rb2
-rw-r--r--app/models/clusters/cluster.rb6
-rw-r--r--app/models/clusters/providers/aws.rb13
-rw-r--r--app/models/clusters/providers/gcp.rb4
-rw-r--r--app/models/project_services/data_fields.rb2
-rw-r--r--app/presenters/clusterable_presenter.rb12
-rw-r--r--app/presenters/instance_clusterable_presenter.rb15
-rw-r--r--app/services/clusters/aws/fetch_credentials_service.rb18
-rw-r--r--app/services/clusters/aws/provision_service.rb12
-rw-r--r--app/services/clusters/aws/proxy_service.rb134
-rw-r--r--app/views/clusters/clusters/_banner.html.haml6
-rw-r--r--app/views/clusters/clusters/aws/_new.html.haml9
13 files changed, 266 insertions, 21 deletions
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
index 5dd4040628f..5d6ce4f342c 100644
--- a/app/controllers/clusters/clusters_controller.rb
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -3,12 +3,12 @@
class Clusters::ClustersController < Clusters::BaseController
include RoutableActions
- before_action :cluster, except: [:index, :new, :create_gcp, :create_user, :authorize_aws_role]
+ before_action :cluster, only: [:cluster_status, :show, :update, :destroy]
before_action :generate_gcp_authorize_url, only: [:new]
before_action :validate_gcp_token, only: [:new]
before_action :gcp_cluster, only: [:new]
before_action :user_cluster, only: [:new]
- before_action :authorize_create_cluster!, only: [:new, :authorize_aws_role]
+ before_action :authorize_create_cluster!, only: [:new, :authorize_aws_role, :revoke_aws_role, :aws_proxy]
before_action :authorize_update_cluster!, only: [:update]
before_action :authorize_admin_cluster!, only: [:destroy]
before_action :update_applications_status, only: [:cluster_status]
@@ -117,6 +117,19 @@ class Clusters::ClustersController < Clusters::BaseController
end
end
+ def create_aws
+ @aws_cluster = ::Clusters::CreateService
+ .new(current_user, create_aws_cluster_params)
+ .execute
+ .present(current_user: current_user)
+
+ if @aws_cluster.persisted?
+ head :created, location: @aws_cluster.show_path
+ else
+ render status: :unprocessable_entity, json: @aws_cluster.errors
+ end
+ end
+
def create_user
@user_cluster = ::Clusters::CreateService
.new(current_user, create_user_cluster_params)
@@ -140,6 +153,21 @@ class Clusters::ClustersController < Clusters::BaseController
role.save ? respond_201 : respond_422
end
+ def revoke_aws_role
+ current_user.aws_role&.destroy
+
+ head :no_content
+ end
+
+ def aws_proxy
+ response = Clusters::Aws::ProxyService.new(
+ current_user.aws_role,
+ params: params
+ ).execute
+
+ render json: response.body, status: response.status
+ end
+
private
def destroy_params
@@ -200,6 +228,28 @@ class Clusters::ClustersController < Clusters::BaseController
)
end
+ def create_aws_cluster_params
+ params.require(:cluster).permit(
+ :enabled,
+ :name,
+ :environment_scope,
+ :managed,
+ provider_aws_attributes: [
+ :key_name,
+ :role_arn,
+ :region,
+ :vpc_id,
+ :instance_type,
+ :num_nodes,
+ :security_group_id,
+ subnet_ids: []
+ ]).merge(
+ provider_type: :aws,
+ platform_type: :kubernetes,
+ clusterable: clusterable.subject
+ )
+ end
+
def create_user_cluster_params
params.require(:cluster).permit(
:enabled,
diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb
index 0cfb45a12e5..0037c49f134 100644
--- a/app/helpers/clusters_helper.rb
+++ b/app/helpers/clusters_helper.rb
@@ -40,7 +40,7 @@ module ClustersHelper
def has_rbac_enabled?(cluster)
return cluster.platform_kubernetes_rbac? if cluster.platform_kubernetes
- !cluster.provider.legacy_abac?
+ cluster.provider.has_rbac_enabled?
end
end
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index 0db1fe9d6dc..ac2b63b194f 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -56,6 +56,7 @@ module Clusters
has_many :kubernetes_namespaces
accepts_nested_attributes_for :provider_gcp, update_only: true
+ accepts_nested_attributes_for :provider_aws, update_only: true
accepts_nested_attributes_for :platform_kubernetes, update_only: true
validates :name, cluster_name: true
@@ -73,6 +74,7 @@ module Clusters
delegate :status, to: :provider, allow_nil: true
delegate :status_reason, to: :provider, allow_nil: true
delegate :on_creation?, to: :provider, allow_nil: true
+ delegate :knative_pre_installed?, to: :provider, allow_nil: true
delegate :active?, to: :platform_kubernetes, prefix: true, allow_nil: true
delegate :rbac?, to: :platform_kubernetes, prefix: true, allow_nil: true
@@ -258,10 +260,6 @@ module Clusters
end
end
- def knative_pre_installed?
- provider&.knative_pre_installed?
- end
-
private
def unique_management_project_environment_scope
diff --git a/app/models/clusters/providers/aws.rb b/app/models/clusters/providers/aws.rb
index 89eb56aa41f..78eb75ddcc0 100644
--- a/app/models/clusters/providers/aws.rb
+++ b/app/models/clusters/providers/aws.rb
@@ -9,7 +9,6 @@ module Clusters
self.table_name = 'cluster_providers_aws'
belongs_to :cluster, inverse_of: :provider_aws, class_name: 'Clusters::Cluster'
- belongs_to :created_by_user, class_name: 'User'
default_value_for :region, 'us-east-1'
default_value_for :num_nodes, 3
@@ -55,6 +54,18 @@ module Clusters
::Aws::Credentials.new(access_key_id, secret_access_key, session_token)
end
end
+
+ def has_rbac_enabled?
+ true
+ end
+
+ def knative_pre_installed?
+ false
+ end
+
+ def created_by_user
+ cluster.user
+ end
end
end
end
diff --git a/app/models/clusters/providers/gcp.rb b/app/models/clusters/providers/gcp.rb
index f871674676f..2ca7d0249dc 100644
--- a/app/models/clusters/providers/gcp.rb
+++ b/app/models/clusters/providers/gcp.rb
@@ -54,6 +54,10 @@ module Clusters
assign_attributes(operation_id: operation_id)
end
+ def has_rbac_enabled?
+ !legacy_abac
+ end
+
def knative_pre_installed?
cloud_run?
end
diff --git a/app/models/project_services/data_fields.rb b/app/models/project_services/data_fields.rb
index cffb493d569..cf406a784ce 100644
--- a/app/models/project_services/data_fields.rb
+++ b/app/models/project_services/data_fields.rb
@@ -50,7 +50,7 @@ module DataFields
end
def data_fields_present?
- data_fields.persisted?
+ data_fields.present?
rescue NotImplementedError
false
end
diff --git a/app/presenters/clusterable_presenter.rb b/app/presenters/clusterable_presenter.rb
index d6f67c1f2e5..2306f55f1f4 100644
--- a/app/presenters/clusterable_presenter.rb
+++ b/app/presenters/clusterable_presenter.rb
@@ -29,10 +29,18 @@ class ClusterablePresenter < Gitlab::View::Presenter::Delegated
new_polymorphic_path([clusterable, :cluster], options)
end
+ def aws_api_proxy_path(resource)
+ polymorphic_path([clusterable, :clusters], action: :aws_proxy, resource: resource)
+ end
+
def authorize_aws_role_path
polymorphic_path([clusterable, :clusters], action: :authorize_aws_role)
end
+ def revoke_aws_role_path
+ polymorphic_path([clusterable, :clusters], action: :revoke_aws_role)
+ end
+
def create_user_clusters_path
polymorphic_path([clusterable, :clusters], action: :create_user)
end
@@ -41,6 +49,10 @@ class ClusterablePresenter < Gitlab::View::Presenter::Delegated
polymorphic_path([clusterable, :clusters], action: :create_gcp)
end
+ def create_aws_clusters_path
+ polymorphic_path([clusterable, :clusters], action: :create_aws)
+ end
+
def cluster_status_cluster_path(cluster, params = {})
raise NotImplementedError
end
diff --git a/app/presenters/instance_clusterable_presenter.rb b/app/presenters/instance_clusterable_presenter.rb
index f820c0f6b42..c6572e8ce71 100644
--- a/app/presenters/instance_clusterable_presenter.rb
+++ b/app/presenters/instance_clusterable_presenter.rb
@@ -52,11 +52,26 @@ class InstanceClusterablePresenter < ClusterablePresenter
create_gcp_admin_clusters_path
end
+ override :create_aws_clusters_path
+ def create_aws_clusters_path
+ create_aws_admin_clusters_path
+ end
+
override :authorize_aws_role_path
def authorize_aws_role_path
authorize_aws_role_admin_clusters_path
end
+ override :revoke_aws_role_path
+ def revoke_aws_role_path
+ revoke_aws_role_admin_clusters_path
+ end
+
+ override :aws_api_proxy_path
+ def aws_api_proxy_path(resource)
+ aws_proxy_admin_clusters_path(resource: resource)
+ end
+
override :empty_state_help_text
def empty_state_help_text
s_('ClusterIntegration|Adding an integration will share the cluster across all projects.')
diff --git a/app/services/clusters/aws/fetch_credentials_service.rb b/app/services/clusters/aws/fetch_credentials_service.rb
index 29442208c62..2724d4b657b 100644
--- a/app/services/clusters/aws/fetch_credentials_service.rb
+++ b/app/services/clusters/aws/fetch_credentials_service.rb
@@ -3,11 +3,13 @@
module Clusters
module Aws
class FetchCredentialsService
- attr_reader :provider
+ attr_reader :provision_role
MissingRoleError = Class.new(StandardError)
- def initialize(provider)
+ def initialize(provision_role, region:, provider: nil)
+ @provision_role = provision_role
+ @region = region
@provider = provider
end
@@ -24,12 +26,10 @@ module Clusters
private
- def provision_role
- provider.created_by_user.aws_role
- end
+ attr_reader :provider, :region
def client
- ::Aws::STS::Client.new(credentials: gitlab_credentials, region: provider.region)
+ ::Aws::STS::Client.new(credentials: gitlab_credentials, region: region)
end
def gitlab_credentials
@@ -45,7 +45,11 @@ module Clusters
end
def session_name
- "gitlab-eks-cluster-#{provider.cluster_id}-user-#{provider.created_by_user_id}"
+ if provider.present?
+ "gitlab-eks-cluster-#{provider.cluster_id}-user-#{provision_role.user_id}"
+ else
+ "gitlab-eks-autofill-user-#{provision_role.user_id}"
+ end
end
end
end
diff --git a/app/services/clusters/aws/provision_service.rb b/app/services/clusters/aws/provision_service.rb
index 6a3b0dffae2..35fe8433b4d 100644
--- a/app/services/clusters/aws/provision_service.rb
+++ b/app/services/clusters/aws/provision_service.rb
@@ -21,7 +21,7 @@ module Clusters
end
rescue Clusters::Aws::FetchCredentialsService::MissingRoleError
provider.make_errored!('Amazon role is not configured')
- rescue ::Aws::Errors::MissingCredentialsError, Settingslogic::MissingSetting
+ rescue ::Aws::Errors::MissingCredentialsError
provider.make_errored!('Amazon credentials are not configured')
rescue ::Aws::STS::Errors::ServiceError => e
provider.make_errored!("Amazon authentication failed; #{e.message}")
@@ -31,8 +31,16 @@ module Clusters
private
+ def provision_role
+ provider.created_by_user&.aws_role
+ end
+
def credentials
- @credentials ||= Clusters::Aws::FetchCredentialsService.new(provider).execute
+ @credentials ||= Clusters::Aws::FetchCredentialsService.new(
+ provision_role,
+ provider: provider,
+ region: provider.region
+ ).execute
end
def configure_provider_credentials
diff --git a/app/services/clusters/aws/proxy_service.rb b/app/services/clusters/aws/proxy_service.rb
new file mode 100644
index 00000000000..df8fc480005
--- /dev/null
+++ b/app/services/clusters/aws/proxy_service.rb
@@ -0,0 +1,134 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Aws
+ class ProxyService
+ DEFAULT_REGION = 'us-east-1'
+
+ BadRequest = Class.new(StandardError)
+ Response = Struct.new(:status, :body)
+
+ def initialize(role, params:)
+ @role = role
+ @params = params
+ end
+
+ def execute
+ api_response = request_from_api!
+
+ Response.new(:ok, api_response.to_hash)
+ rescue *service_errors
+ Response.new(:bad_request, {})
+ end
+
+ private
+
+ attr_reader :role, :params
+
+ def request_from_api!
+ case requested_resource
+ when 'key_pairs'
+ ec2_client.describe_key_pairs
+
+ when 'instance_types'
+ instance_types
+
+ when 'roles'
+ iam_client.list_roles
+
+ when 'regions'
+ ec2_client.describe_regions
+
+ when 'security_groups'
+ raise BadRequest unless vpc_id.present?
+
+ ec2_client.describe_security_groups(vpc_filter)
+
+ when 'subnets'
+ raise BadRequest unless vpc_id.present?
+
+ ec2_client.describe_subnets(vpc_filter)
+
+ when 'vpcs'
+ ec2_client.describe_vpcs
+
+ else
+ raise BadRequest
+ end
+ end
+
+ def requested_resource
+ params[:resource]
+ end
+
+ def vpc_id
+ params[:vpc_id]
+ end
+
+ def region
+ params[:region] || DEFAULT_REGION
+ end
+
+ def vpc_filter
+ {
+ filters: [{
+ name: "vpc-id",
+ values: [vpc_id]
+ }]
+ }
+ end
+
+ ##
+ # Unfortunately the EC2 API doesn't provide a list of
+ # possible instance types. There is a workaround, using
+ # the Pricing API, but instead of requiring the
+ # user to grant extra permissions for this we use the
+ # values that validate the CloudFormation template.
+ def instance_types
+ {
+ instance_types: cluster_stack_instance_types.map { |type| Hash(instance_type_name: type) }
+ }
+ end
+
+ def cluster_stack_instance_types
+ YAML.safe_load(stack_template).dig('Parameters', 'NodeInstanceType', 'AllowedValues')
+ end
+
+ def stack_template
+ File.read(Rails.root.join('vendor', 'aws', 'cloudformation', 'eks_cluster.yaml'))
+ end
+
+ def ec2_client
+ ::Aws::EC2::Client.new(client_options)
+ end
+
+ def iam_client
+ ::Aws::IAM::Client.new(client_options)
+ end
+
+ def credentials
+ Clusters::Aws::FetchCredentialsService.new(role, region: region).execute
+ end
+
+ def client_options
+ {
+ credentials: credentials,
+ region: region,
+ http_open_timeout: 5,
+ http_read_timeout: 10
+ }
+ end
+
+ def service_errors
+ [
+ BadRequest,
+ Clusters::Aws::FetchCredentialsService::MissingRoleError,
+ ::Aws::Errors::MissingCredentialsError,
+ ::Aws::EC2::Errors::ServiceError,
+ ::Aws::IAM::Errors::ServiceError,
+ ::Aws::STS::Errors::ServiceError
+ ]
+ end
+ end
+ end
+end
diff --git a/app/views/clusters/clusters/_banner.html.haml b/app/views/clusters/clusters/_banner.html.haml
index 4b4278075a6..7d97aaccbcf 100644
--- a/app/views/clusters/clusters/_banner.html.haml
+++ b/app/views/clusters/clusters/_banner.html.haml
@@ -1,10 +1,10 @@
.hidden.js-cluster-error.bs-callout.bs-callout-danger{ role: 'alert' }
- = s_('ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine')
+ = s_('ClusterIntegration|Something went wrong while creating your Kubernetes cluster')
%p.js-error-reason
.hidden.js-cluster-creating.bs-callout.bs-callout-info{ role: 'alert' }
%span.spinner.spinner-dark.spinner-sm{ 'aria-label': 'Loading' }
- %span.prepend-left-4= s_('ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine...')
+ %span.prepend-left-4= s_('ClusterIntegration|Kubernetes cluster is being created...')
.hidden.row.js-cluster-api-unreachable.bs-callout.bs-callout-warning{ role: 'alert' }
.col-11
@@ -19,4 +19,4 @@
%button.js-close-banner.close.cluster-application-banner-close.h-100.m-0= "×"
.hidden.js-cluster-success.bs-callout.bs-callout-success{ role: 'alert' }
- = s_("ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine.")
+ = s_("ClusterIntegration|Kubernetes cluster was successfully created.")
diff --git a/app/views/clusters/clusters/aws/_new.html.haml b/app/views/clusters/clusters/aws/_new.html.haml
index fe8b606af70..48467f88f52 100644
--- a/app/views/clusters/clusters/aws/_new.html.haml
+++ b/app/views/clusters/clusters/aws/_new.html.haml
@@ -4,6 +4,15 @@
- else
.js-create-eks-cluster-form-container{ data: { 'gitlab-managed-cluster-help-path' => help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'),
'create-role-path' => clusterable.authorize_aws_role_path,
+ 'sign-out-path' => clusterable.revoke_aws_role_path,
+ 'create-cluster-path' => clusterable.create_aws_clusters_path,
+ 'get-roles-path' => clusterable.aws_api_proxy_path('roles'),
+ 'get-regions-path' => clusterable.aws_api_proxy_path('regions'),
+ 'get-key-pairs-path' => clusterable.aws_api_proxy_path('key_pairs'),
+ 'get-vpcs-path' => clusterable.aws_api_proxy_path('vpcs'),
+ 'get-subnets-path' => clusterable.aws_api_proxy_path('subnets'),
+ 'get-security-groups-path' => clusterable.aws_api_proxy_path('security_groups'),
+ 'get-instance-types-path' => clusterable.aws_api_proxy_path('instance_types'),
'account-id' => Gitlab::CurrentSettings.eks_account_id,
'external-id' => @aws_role.role_external_id,
'kubernetes-integration-help-path' => help_page_path('user/project/clusters/index'),