forked from Trustie/forgeplus
ADD test devops
This commit is contained in:
parent
dbafd32d0b
commit
e74bba9092
|
@ -0,0 +1,64 @@
|
|||
class DevOps::CloudAccountsController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :find_project
|
||||
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
DevOps::CreateCloudAccountForm.new(devops_params).validate!
|
||||
logger.info "######### devops_params: #{devops_params}"
|
||||
logger.info "######### ......: #{(IPAddr.new devops_params[:ip_num]).to_i}"
|
||||
logger.info "######### ......: #{DevopsCloudAccount.encrypted_secret(devops_params[:secret])}"
|
||||
# 1. 保存华为云服务器帐号
|
||||
logger.info "######### ......ff: #{devops_params.merge(ip_num: IPAddr.new(devops_params[:ip_num]).to_i, secret: DevopsCloudAccount.encrypted_secret(devops_params[:secret]))}"
|
||||
create_params = devops_params.merge(ip_num: IPAddr.new(devops_params[:ip_num]).to_i, secret: DevopsCloudAccount.encrypted_secret(devops_params[:secret]))
|
||||
logger.info "######### create_params: #{create_params}"
|
||||
cloud_account = DevopsCloudAccount.new(create_params)
|
||||
cloud_account.user = current_user
|
||||
cloud_account.save
|
||||
# 2. 生成oauth2应用程序的client_id和client_secrete
|
||||
gitea_oauth = Gitea::Oauth2::CreateService.call(current_user.gitea_token, {name: "pipeline", redirect_uris: [cloud_account.drone_url]})
|
||||
logger.info "######### gitea_oauth: #{gitea_oauth}"
|
||||
oauth = Oauth.new(client_id: gitea_oauth['client_id'],
|
||||
client_secret: gitea_oauth['client_secret'],
|
||||
redirect_uri: gitea_oauth['redirect_uris'],
|
||||
gitea_oauth_id: gitea_oauth['id'],
|
||||
user_id: current_user.id,
|
||||
project_id: devops_params[:project_id])
|
||||
oauth.save
|
||||
|
||||
rpc_secret = SecureRandom.hex 16
|
||||
logger.info "######### rpc_secret: #{rpc_secret}"
|
||||
# 3. 创建drone server
|
||||
drone_server_cmd = DevOps::Drone::Server.new(oauth.client_id, oauth.client_secret, cloud_account.drone_host, rpc_secret).generate_cmd
|
||||
logger.info "######### drone_server_cmd: #{drone_server_cmd}"
|
||||
|
||||
# 4. 创建drone client
|
||||
drone_client_cmd = DevOps::Drone::Client.new(oauth.client_id, cloud_account.drone_ip, rpc_secret).generate_cmd
|
||||
logger.info "######### drone_client_cmd: #{drone_client_cmd}"
|
||||
|
||||
# 5. 登录远程服务器,启动drone服务
|
||||
result = DevOps::Drone::Start.new(cloud_account.account, cloud_account.visible_secret, cloud_account.drone_ip, drone_server_cmd, drone_client_cmd).run
|
||||
logger.info "######### result: #{result}"
|
||||
|
||||
|
||||
redirect_url = "#{Gitea.gitea_config[:domain]}/login/oauth/authorize?client_id=#{oauth.client_id}&redirect_uri=#{cloud_account.drone_url}/login&response_type=code"
|
||||
if result
|
||||
render_ok(redirect_url: redirect_url)
|
||||
else
|
||||
render_error('激活失败')
|
||||
end
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
end
|
||||
|
||||
private
|
||||
def devops_params
|
||||
params.permit(:account, :secret, :ip_num, :project_id)
|
||||
end
|
||||
|
||||
def find_project
|
||||
@project = Project.find_by_id params[:project_id]
|
||||
render_not_found("未找到project_id为:#{params[:project_id]}相关的项目") if @project.blank?
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
class DevOps::CreateCloudAccountForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :project_id, :ip_num, :account, :secret
|
||||
|
||||
validates :project_id, :account, :secret, presence: true
|
||||
validates :ip_num, presence: true, format: { with: CustomRegexp::IP, multiline: true, message: 'IP 地址格式不对' }
|
||||
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
module DevOpsHelper
|
||||
end
|
|
@ -5,4 +5,5 @@ module CustomRegexp
|
|||
NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/
|
||||
PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/
|
||||
URL = /\Ahttps?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]\z/
|
||||
end
|
||||
IP = /^((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/
|
||||
end
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
class DevOps::Drone::Ci
|
||||
attr_reader :host, :username, :password
|
||||
|
||||
# host: drone server's ip
|
||||
# username: drone server's account
|
||||
# password: drone server's password
|
||||
# eq:
|
||||
# DevOps::Drone::Ci.new(@cloud_account.drone_ip, @cloud_account.account, @cloud_account.visible_secret).get_token
|
||||
def initialize(host, username, password)
|
||||
@host = host
|
||||
@username = username
|
||||
@password = password
|
||||
end
|
||||
|
||||
def get_token
|
||||
`sshpass -p #{password} ssh -o "StrictHostKeyChecking no" #{username}@#{host} "#{cmd}"`
|
||||
end
|
||||
|
||||
private
|
||||
def cmd
|
||||
"cd ..; cd var/lib/drone/; sqlite3 database.sqlite; .dump; select user_hash from users where user_login=#{username} "
|
||||
end
|
||||
end
|
|
@ -0,0 +1,39 @@
|
|||
class DevOps::Drone::Client
|
||||
attr_reader :client_id, :drone_ip, :rpc_secret
|
||||
|
||||
# client_id: user's client_id from oauth
|
||||
# drone_ip: 云服务器IP地址, eq: 173.65.32.21
|
||||
# eq:
|
||||
# DevOps::Drone::Client.new(current_user.oauth.client_id, 'drone_ip').generate_cmd
|
||||
def initialize(client_id, drone_ip, rpc_secret)
|
||||
@client_id = client_id
|
||||
@drone_ip = drone_ip
|
||||
@rpc_secret = rpc_secret
|
||||
end
|
||||
|
||||
def run
|
||||
`docker run -d \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-e DRONE_RPC_SERVER=drone-server-#{client_id}:9000 \
|
||||
-e DRONE_RPC_SECRET=#{rpc_secret} \
|
||||
-e DRONE_RUNNER_NAME=#{drone_ip} \
|
||||
--restart always \
|
||||
--name drone-agent--#{client_id} \
|
||||
--net="bridge" \
|
||||
drone/drone-runner-docker:1
|
||||
`
|
||||
end
|
||||
|
||||
def generate_cmd
|
||||
"docker run -d \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-e DRONE_RPC_SERVER=drone-server-#{client_id}:9000 \
|
||||
-e DRONE_RPC_SECRET=#{rpc_secret} \
|
||||
-e DRONE_RUNNER_NAME=#{drone_ip} \
|
||||
--restart always \
|
||||
--name drone-agent--#{client_id} \
|
||||
--net='bridge' \
|
||||
drone/drone-runner-docker:1
|
||||
"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,59 @@
|
|||
class DevOps::Drone::Server
|
||||
attr_reader :client_id, :client_secret, :drone_host, :rpc_secret
|
||||
|
||||
# client_id: user's client_id from oauth
|
||||
# client_secret: user's client_id from oauth
|
||||
# drone_host: 云服务器地址,eq: 173.53.21.31:80
|
||||
# eg:
|
||||
# DevOps::Drone::Server.new(current_user.oauth.client_id, current_user.oauth.client_secret, 'drone_host').generate_cmd
|
||||
def initialize(client_id, client_secret, drone_host, rpc_secret)
|
||||
@client_id = client_id
|
||||
@drone_host = drone_host
|
||||
@rpc_secret = rpc_secret
|
||||
@client_secret = client_secret
|
||||
end
|
||||
|
||||
def run
|
||||
`
|
||||
docker run \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-e DRONE_GITEA_SERVER=#{gitea_url} \
|
||||
-e DRONE_GITEA_CLIENT_ID=#{client_id} \
|
||||
-e DRONE_GITEA_CLIENT_SECRET=#{client_secret} \
|
||||
-e DRONE_RPC_SECRET=#{rpc_secret} \
|
||||
-e DRONE_SERVER_HOST=#{drone_host} \
|
||||
-e DRONE_SERVER_PROTO=http \
|
||||
-p "80:80" \
|
||||
-p "9000:9000" \
|
||||
--restart=always \
|
||||
--detach=true \
|
||||
--name=drone-server-#{client_id} \
|
||||
--net="bridge" \
|
||||
drone/drone:1
|
||||
`
|
||||
end
|
||||
|
||||
def generate_cmd
|
||||
"service docker start; docker run \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-e DRONE_GITEA_SERVER=#{gitea_url} \
|
||||
-e DRONE_GITEA_CLIENT_ID=#{client_id} \
|
||||
-e DRONE_GITEA_CLIENT_SECRET=#{client_secret} \
|
||||
-e DRONE_RPC_SECRET=#{rpc_secret} \
|
||||
-e DRONE_SERVER_HOST=#{drone_host} \
|
||||
-e DRONE_SERVER_PROTO=http \
|
||||
-p '80:80' \
|
||||
-p '9000:9000' \
|
||||
--restart=always \
|
||||
--detach=true \
|
||||
--name=drone-server-#{client_id} \
|
||||
--net='bridge' \
|
||||
drone/drone:1
|
||||
"
|
||||
end
|
||||
|
||||
private
|
||||
def gitea_url
|
||||
Gitea.gitea_config[:domain]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
class DevOps::Drone::Start
|
||||
attr_reader :drone_username, :drone_password, :drone_host, :drone_server_cmd, :drone_client_cmd
|
||||
|
||||
# drone_username="XXXX" 云服务器登录用户名
|
||||
# drone_password="XXXXX" 云服务器用户密码
|
||||
# drone_host="" 云服务器地址
|
||||
# eq:
|
||||
# drone_server_cmd = DevOps::Drone::Server.new('client_id', 'client_secret', 'drone_url').generate_cmd
|
||||
# drone_client_cmd = DevOps::Drone::Client.new('client_id', 'server_url').generate_cmd
|
||||
# DevOps::Drone::Start.new(drone_username, drone_password, 'drone_host', drone_server_cmd, drone_client_cmd).run
|
||||
def initialize(drone_username, drone_password, drone_host, drone_server_cmd, drone_client_cmd)
|
||||
@drone_username = drone_username
|
||||
@drone_password = drone_password
|
||||
@drone_host = drone_host
|
||||
@drone_server_cmd = drone_server_cmd
|
||||
@drone_client_cmd = drone_client_cmd
|
||||
end
|
||||
|
||||
def run
|
||||
`sshpass -p #{drone_password} ssh -o "StrictHostKeyChecking no" #{drone_username}@#{drone_host} "#{drone_server_cmd} && #{drone_client_cmd}"`
|
||||
end
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
class DevopsCloudAccount < ApplicationRecord
|
||||
belongs_to :project
|
||||
belongs_to :user
|
||||
|
||||
|
||||
def drone_host
|
||||
[drone_ip, ":80"].join
|
||||
end
|
||||
|
||||
def drone_ip
|
||||
IPAddr.new(self.ip_num, Socket::AF_INET).to_s
|
||||
end
|
||||
|
||||
def drone_url
|
||||
["http://", drone_host].join
|
||||
end
|
||||
|
||||
def visible_secret
|
||||
Base64.decode64(secret)
|
||||
end
|
||||
|
||||
def self.encrypted_secret(str)
|
||||
Base64.encode64(str.strip).gsub(/\n/, '')
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
# for oauth2 application
|
||||
class Oauth < ApplicationRecord
|
||||
belongs_to :project
|
||||
belongs_to :user
|
||||
end
|
|
@ -161,7 +161,7 @@ class Project < ApplicationRecord
|
|||
member&.roles&.last&.name || permission
|
||||
end
|
||||
|
||||
def fork_project
|
||||
def fork_project
|
||||
Project.find_by(id: self.forked_from_project_id)
|
||||
end
|
||||
|
||||
|
|
|
@ -21,9 +21,6 @@ class Gitea::ClientService < ApplicationService
|
|||
def post(url, params={})
|
||||
puts "[gitea] request params: #{params}"
|
||||
request_url = [api_url, url].join('').freeze
|
||||
Rails.logger.info("######_____api____request_url_______###############{request_url}")
|
||||
Rails.logger.info("######_____api____request_params_______###############{params}")
|
||||
|
||||
auth_token = authen_params(params[:token])
|
||||
response = conn(auth_token).post do |req|
|
||||
req.url "#{request_url}"
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
# creates a new OAuth2 application
|
||||
class Gitea::Oauth2::CreateService < Gitea::ClientService
|
||||
attr_reader :token, :params
|
||||
|
||||
# params:
|
||||
# {
|
||||
# "name": "string",
|
||||
# "redirect_uris": [
|
||||
# "string"
|
||||
# ]
|
||||
# }
|
||||
# ep: Gitea::OAuth2::CreateService.call(current_user.gitea_token, {name: 'oauth_name', redirect_uris: ['url']})
|
||||
# return values example:
|
||||
# {
|
||||
# "client_id": "string",
|
||||
# "client_secret": "string",
|
||||
# "created": "2020-07-08T03:12:49.960Z",
|
||||
# "id": 0,
|
||||
# "name": "string",
|
||||
# "redirect_uris": [
|
||||
# "string"
|
||||
# ]
|
||||
# }
|
||||
def initialize(token, params)
|
||||
@token = token
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
post(url, request_params)
|
||||
end
|
||||
|
||||
private
|
||||
def url
|
||||
"/user/applications/oauth2".freeze
|
||||
end
|
||||
|
||||
def request_params
|
||||
params.merge(token: token, data: params).compact
|
||||
end
|
||||
end
|
|
@ -1,5 +1,5 @@
|
|||
Rails.application.routes.draw do
|
||||
|
||||
|
||||
require 'sidekiq/web'
|
||||
require 'admin_constraint'
|
||||
|
||||
|
@ -16,6 +16,10 @@ Rails.application.routes.draw do
|
|||
resources :edu_settings
|
||||
|
||||
scope '/api' do
|
||||
namespace :dev_ops do
|
||||
resources :cloud_accounts, only: [:create]
|
||||
end
|
||||
|
||||
resources :composes do
|
||||
resources :compose_projects, only: [:create, :destroy]
|
||||
end
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
class CreateDevopsCloudAccounts < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :devops_cloud_accounts do |t|
|
||||
t.integer :project_id, null: false
|
||||
t.integer :user_id, null: false
|
||||
t.integer :ip_num, null: false
|
||||
t.string :account, null: false
|
||||
t.string :secret, null: false
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
add_index :devops_cloud_accounts, [:project_id, :user_id, :ip_num]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
class AddGiteaOauthIdAndProjectIdToOauths < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_column :oauths, :gitea_oauth_id, :integer
|
||||
add_column :oauths, :project_id, :integer
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue