Read about our upcoming Code of Conduct on this issue

Commit d4fa672c authored by Shinya Maeda's avatar Shinya Maeda
Browse files

Create Kubernetes cluster on GKE from k8s service

parent 6c4af41c4723
module GoogleApi
class AuthorizationsController < ApplicationController
# callback_google_api_authorizations GET|POST /google_api/authorizations/callback(.:format) google_api/authorizations#callback
##
# TODO:
# - Is it ok to use both "http://localhost:3000/google_api/authorizations/callback"(For login) and "http://localhost:3000/google_api/authorizations/callback"(For API token)
def callback
session[access_token_key] = api_client.get_token(params[:code])
if params[:state]
redirect_to params[:state]
else
redirect_to root_url
end
end
def api_client
@api_client ||=
GoogleApi::Authentication.new(nil, callback_google_api_authorizations_url)
end
def access_token_key
# :"#{api_client.scope}_access_token"
:"hoge_access_token" # TODO:
end
end
end
class Projects::ClustersController < Projects::ApplicationController
# before_action :authenticate_google_api
before_action :cluster
# before_action :authorize_admin_clusters! # TODO: Authentication
def index
if cluster
redirect_to action: 'edit'
else
redirect_to action: 'new'
end
end
##
# TODO:
# - Show form for "Create on Google Container Engine"
# - Show form for "Use existing kubernets cluster"
# - If user has not authroized yet, Show "Sign in with Google" button
# - If user has already authroized, Skip "Sign in with Google" button
# - user.is_authenticated_for_gcp?
# - user.authenticate_for_gcp!
# - Create this module which can be used from view
def new
unless session[access_token_key]
@authorize_url = api_client.authorize_url
end
end
##
# TODO:
# - If create on GKE, Use Google::Apis::ContainerV1::ContainerService
# - If create manually, save in db (Prob, Project > Setting)
# - Dry up with Service
def create
redirect_to action: 'index'
end
# TODO: Show results/status. Edits Swtich for enable/disable.
# If created with GKE, non-editable form. enable/disable switch.
# If created manually, editable form. enable/disable switch.
# GKE params are on-off swtich
# Manul params are on-off swtich, Endpoint, CACert, k8s Token, Proj namespace.
def edit
unless session[access_token_key]
@authorize_url = api_client.authorize_url
end
end
def update
cluster.update(schedule_params)
render :edit
end
# In presenter
# TODO: Generate a link to the cluster on GKE
def gcp_projects
# api_client.blah
# TODO: Return all avaiable GCP Projects.
# TODO: Return json
# TODO: Dry with concern
end
def gke_zones
# api_client.blah
# TODO: Return all avaiable zones on GKE.
# TODO: Return json
# TODO: Dry with concern
end
private
# def authenticate_google_api
# if cluster&.on_gke? && session[access_token_key].blank?
# redirect_to api_client.authorize_url(callback_import_url)
# end
# end
def cluster
# Each project has only one cluster, for now. In the future iteraiton, we'll support multiple clusters
@cluster ||= project.clusters.first
end
def cluster_params
params.require(:cluster).permit(:aaa)
end
def api_client
@api_client ||=
GoogleApi::CloudPlatform::Client.new(
session[access_token_key],
callback_google_api_authorizations_url,
state: namespace_project_clusters_url.to_s
)
end
def access_token_key
# :"#{api_client.scope}_access_token"
:"hoge_access_token" # TODO:
end
end
module Ci
class Cluster < ActiveRecord::Base
extend Gitlab::Ci::Model
belongs_to :project
belongs_to :owner, class_name: 'User'
enum creation_type: {
unknown: nil,
on_gke: 1,
manual: 2
}
end
end
......@@ -171,6 +171,7 @@ class Project < ActiveRecord::Base
has_many :commit_statuses
has_many :pipelines, class_name: 'Ci::Pipeline'
has_many :clusters, class_name: 'Ci::Cluster'
# Ci::Build objects store data on the file system such as artifact files and
# build traces. Currently there's no efficient way of removing this data in
......
edit/show cluster
= @cluster.inspect
Create a new cluster
%br
- if @authorize_url
I have not authenticated yet. I can authenticate from
= link_to("authenticate from here", @authorize_url)
- else
I have already authenticated.
%br
Avaiable GCP project lists
%br
Avaiable zones
%br
= link_to "Create on Google Container Engine", namespace_project_clusters_path(@project.namespace, @project, param1: 'value1', param2: 'value2'), method: :post
= link_to "Use existing kubernets cluster", namespace_project_clusters_path(@project.namespace, @project, param1: 'value1', param2: 'value2'), method: :post
......@@ -87,6 +87,7 @@
resources :issues, module: :boards, only: [:index, :update]
end
draw :google_api
draw :import
draw :uploads
draw :explore
......
namespace :google_api do
resource :authorizations, only: [], controller: :authorizations do
match :callback, via: [:get, :post]
end
end
......@@ -183,6 +183,13 @@
end
end
resources :clusters, except: [:show, :destroy] do
collection do
get :gcp_projects # TODO: This doesn't belong here. Grape or under user. Hint. Serilizer
get :gke_zones
end
end
resources :environments, except: [:destroy] do
member do
post :stop
......
class CreateCiClusters < ActiveRecord::Migration
DOWNTIME = false
def change
create_table :ci_clusters do |t|
t.integer :project_id
t.integer :owner_id
t.datetime_with_timezone :created_at, null: false
t.datetime_with_timezone :updated_at, null: false
t.boolean :enabled, default: true
t.string :end_point
t.text :ca_cert # Base64?
t.string :token
t.string :username
t.string :password
t.string :project_namespace
t.integer :creation_type # manual or on_gke
end
# TODO: fk, index, encypt
add_foreign_key :ci_clusters, :projects
add_foreign_key :ci_clusters, :users, column: :owner_id
end
def down
drop_table :ci_clusters
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170921115009) do
ActiveRecord::Schema.define(version: 20170924094327) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -32,8 +32,8 @@
t.text "description", null: false
t.string "header_logo"
t.string "logo"
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "description_html"
t.integer "cached_markdown_version"
end
......@@ -101,10 +101,6 @@
t.text "help_page_text_html"
t.text "shared_runners_text_html"
t.text "after_sign_up_text_html"
t.integer "rsa_key_restriction", default: 0, null: false
t.integer "dsa_key_restriction", default: 0, null: false
t.integer "ecdsa_key_restriction", default: 0, null: false
t.integer "ed25519_key_restriction", default: 0, null: false
t.boolean "housekeeping_enabled", default: true, null: false
t.boolean "housekeeping_bitmaps_enabled", default: true, null: false
t.integer "housekeeping_incremental_repack_period", default: 10, null: false
......@@ -132,6 +128,10 @@
t.boolean "password_authentication_enabled"
t.integer "performance_bar_allowed_group_id"
t.boolean "hashed_storage_enabled", default: false, null: false
t.integer "rsa_key_restriction", default: 0, null: false
t.integer "dsa_key_restriction", default: 0, null: false
t.integer "ecdsa_key_restriction", default: 0, null: false
t.integer "ed25519_key_restriction", default: 0, null: false
t.boolean "project_export_enabled", default: true, null: false
t.boolean "auto_devops_enabled", default: false, null: false
end
......@@ -256,7 +256,6 @@
add_index "ci_builds", ["commit_id", "status", "type"], name: "index_ci_builds_on_commit_id_and_status_and_type", using: :btree
add_index "ci_builds", ["commit_id", "type", "name", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_name_and_ref", using: :btree
add_index "ci_builds", ["commit_id", "type", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_ref", using: :btree
add_index "ci_builds", ["id"], name: "index_for_ci_builds_retried_migration", where: "(retried IS NULL)", using: :btree
add_index "ci_builds", ["project_id"], name: "index_ci_builds_on_project_id", using: :btree
add_index "ci_builds", ["protected"], name: "index_ci_builds_on_protected", using: :btree
add_index "ci_builds", ["runner_id"], name: "index_ci_builds_on_runner_id", using: :btree
......@@ -267,6 +266,21 @@
add_index "ci_builds", ["updated_at"], name: "index_ci_builds_on_updated_at", using: :btree
add_index "ci_builds", ["user_id"], name: "index_ci_builds_on_user_id", using: :btree
create_table "ci_clusters", force: :cascade do |t|
t.integer "project_id"
t.integer "owner_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "enabled", default: true
t.string "end_point"
t.text "ca_cert"
t.string "token"
t.string "username"
t.string "password"
t.string "project_namespace"
t.integer "creation_type"
end
create_table "ci_group_variables", force: :cascade do |t|
t.string "key", null: false
t.text "value"
......@@ -275,8 +289,8 @@
t.string "encrypted_value_iv"
t.integer "group_id", null: false
t.boolean "protected", default: false, null: false
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "ci_group_variables", ["group_id", "key"], name: "index_ci_group_variables_on_group_id_and_key", unique: true, using: :btree
......@@ -288,8 +302,8 @@
t.string "encrypted_value_salt"
t.string "encrypted_value_iv"
t.integer "pipeline_schedule_id", null: false
t.datetime_with_timezone "created_at"
t.datetime_with_timezone "updated_at"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "ci_pipeline_schedule_variables", ["pipeline_schedule_id", "key"], name: "index_ci_pipeline_schedule_variables_on_schedule_id_and_key", unique: true, using: :btree
......@@ -341,12 +355,14 @@
t.integer "auto_canceled_by_id"
t.integer "pipeline_schedule_id"
t.integer "source"
t.integer "config_source"
t.boolean "protected"
t.integer "iid"
t.integer "config_source"
end
add_index "ci_pipelines", ["auto_canceled_by_id"], name: "index_ci_pipelines_on_auto_canceled_by_id", using: :btree
add_index "ci_pipelines", ["pipeline_schedule_id"], name: "index_ci_pipelines_on_pipeline_schedule_id", using: :btree
add_index "ci_pipelines", ["project_id", "iid"], name: "index_ci_pipelines_on_project_id_and_iid", unique: true, using: :btree
add_index "ci_pipelines", ["project_id", "ref", "status"], name: "index_ci_pipelines_on_project_id_and_ref_and_status", using: :btree
add_index "ci_pipelines", ["project_id", "sha"], name: "index_ci_pipelines_on_project_id_and_sha", using: :btree
add_index "ci_pipelines", ["project_id"], name: "index_ci_pipelines_on_project_id", using: :btree
......@@ -538,8 +554,8 @@
t.integer "project_id"
t.integer "author_id", null: false
t.integer "target_id"
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "action", limit: 2, null: false
t.string "target_type"
end
......@@ -577,8 +593,8 @@
add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
create_table "gpg_keys", force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.binary "primary_keyid"
t.binary "fingerprint"
......@@ -590,8 +606,8 @@
add_index "gpg_keys", ["user_id"], name: "index_gpg_keys_on_user_id", using: :btree
create_table "gpg_signatures", force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "project_id"
t.integer "gpg_key_id"
t.binary "commit_sha"
......@@ -789,8 +805,8 @@
add_index "members", ["user_id"], name: "index_members_on_user_id", using: :btree
create_table "merge_request_diff_commits", id: false, force: :cascade do |t|
t.datetime_with_timezone "authored_date"
t.datetime_with_timezone "committed_date"
t.datetime "authored_date"
t.datetime "committed_date"
t.integer "merge_request_diff_id", null: false
t.integer "relative_order", null: false
t.binary "sha", null: false
......@@ -1113,8 +1129,8 @@
create_table "project_auto_devops", force: :cascade do |t|
t.integer "project_id", null: false
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "enabled"
t.string "domain"
end
......@@ -1204,7 +1220,6 @@
t.string "repository_storage", default: "default", null: false
t.boolean "request_access_enabled", default: false, null: false
t.boolean "has_external_wiki"
t.string "ci_config_path"
t.boolean "lfs_enabled"
t.text "description_html"
t.boolean "only_allow_merge_if_all_discussions_are_resolved"
......@@ -1212,8 +1227,9 @@
t.integer "auto_cancel_pending_pipelines", default: 1, null: false
t.string "import_jid"
t.integer "cached_markdown_version"
t.text "delete_error"
t.datetime "last_repository_updated_at"
t.string "ci_config_path"
t.text "delete_error"
t.integer "storage_version", limit: 2
t.boolean "resolve_outdated_diff_discussions"
end
......@@ -1685,6 +1701,8 @@
add_foreign_key "ci_builds", "ci_pipelines", column: "auto_canceled_by_id", name: "fk_a2141b1522", on_delete: :nullify
add_foreign_key "ci_builds", "ci_stages", column: "stage_id", name: "fk_3a9eaa254d", on_delete: :cascade
add_foreign_key "ci_builds", "projects", name: "fk_befce0568a", on_delete: :cascade
add_foreign_key "ci_clusters", "projects"
add_foreign_key "ci_clusters", "users", column: "owner_id"
add_foreign_key "ci_group_variables", "namespaces", column: "group_id", name: "fk_33ae4d58d8", on_delete: :cascade
add_foreign_key "ci_pipeline_schedule_variables", "ci_pipeline_schedules", column: "pipeline_schedule_id", name: "fk_41c35fda51", on_delete: :cascade
add_foreign_key "ci_pipeline_schedules", "projects", name: "fk_8ead60fcc4", on_delete: :cascade
......
module GoogleApi
class Authentication
attr_reader :access_token, :redirect_uri, :state
def initialize(access_token, redirect_uri, state: nil)
@access_token = access_token
@redirect_uri = redirect_uri
@state = state
end
def client
return @client if defined?(@client)
unless config
raise 'OAuth configuration for google_oauth2 missing.'
end
@client = ::OAuth2::Client.new(
config.app_id,
config.app_secret,
site: 'https://accounts.google.com',
token_url: '/o/oauth2/token',
authorize_url: '/o/oauth2/auth'
)
end
def authorize_url
client.auth_code.authorize_url(
redirect_uri: redirect_uri,
scope: scope,
state: state # This is used for arbitary redirection
)
end
def get_token(code)
client.auth_code.get_token(code, redirect_uri: redirect_uri).token
end
protected
def scope
raise NotImplementedError
end
private
def config
Gitlab.config.omniauth.providers.find { |provider| provider.name == "google_oauth2" }
end
end
end
module GoogleApi
module CloudPlatform
class Client < GoogleApi::Authentication
# Google::Apis::ContainerV1::ContainerService.new
def scope
'https://www.googleapis.com/auth/cloud-platform'
end
def projects_zones_clusters_get
# TODO:
# service = Google::Apis::ContainerV1::ContainerService.new
# service.authorization = access_token
# project_id = params['project_id']
# ...
# response = service.list_zone_clusters(project_id, zone)
response
end
def projects_zones_clusters_create
# TODO
end
end
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment