#376: added NodeInstruction

This commit is contained in:
Vokhmin Alexey V 2014-04-15 01:32:25 +04:00
parent b577cd2b60
commit 5b734e3006
6 changed files with 189 additions and 40 deletions

View File

@ -0,0 +1,68 @@
ActiveAdmin.register NodeInstruction do
menu priority: 3
controller do
def scoped_collection
NodeInstruction.includes(:user)
end
end
filter :user_uname, as: :string
filter :status, as: :select, collection: NodeInstruction::STATUSES
filter :updated_at
index do
column :id
column :user
column(:status, sortable: :status) do |ni|
status_tag(ni.status, status_color(ni))
end
column :updated_at
default_actions
end
form do |f|
f.inputs do
f.input :user, as: :select, include_blank: false, collection: User.system.map { |u| [u.uname, u.id] }
f.input :status, as: :select, include_blank: false, collection: NodeInstruction::STATUSES
f.input :instruction, as: :text
end
f.actions
end
show do
attributes_table do
row :id
row :user
row(:status, sortable: :status) do |ni|
status_tag(ni.status, status_color(ni))
end
row :created_at
row :updated_at
row :instruction
row :output
end
end
sidebar 'Actions', only: :show do
%w(disable ready check restart fail).each do |state|
div do
link_to state.humanize, force_admin_node_instruction_path(resource, state: state), method: :patch
end if resource.send("can_#{state}?")
end
end
member_action :force, method: :patch do
if NodeInstruction::STATUSES.include?(params[:state])
resource.send(params[:state])
flash[:info] = 'Action added to queue successfully'
end
redirect_to admin_node_instruction_path(resource)
end
end

View File

@ -0,0 +1,12 @@
def status_color(ni)
case
when ni.ready?
:green
when ni.disabled?
nil
when ni.failed?
:red
else
:orange
end
end

View File

@ -0,0 +1,45 @@
class NodeInstruction < ActiveRecord::Base
STATUSES = [
DISABLED = 'disabled',
READY = 'ready',
CHECKING = 'checking',
RESTARTING = 'restarting',
FAILED = 'failed'
]
belongs_to :user
attr_encrypted :instruction, key: APP_CONFIG['keys']['node_instruction_secret_key']
validates :user, presence: true
validates :instruction, presence: true, length: { maximum: 10000 }
validates :status, presence: true
validate -> {
errors.add(:status, 'Can be only single active instruction for each node') if !disabled? && NodeInstruction.where('id != ?', id.to_i).where(user_id: user_id, status: STATUSES - [DISABLED]).exists?
}
attr_accessible :instruction, :user_id, :output, :status
state_machine :status, initial: :ready do
event :ready do
transition %i(ready restarting disabled failed checking) => :ready
end
event :disable do
transition ready: :disabled
end
event :check do
transition ready: :checking
end
event :restart do
transition checking: :restarting
end
event :fail do
transition %i(restarting checking) => :failed
end
end
end

View File

@ -14,6 +14,7 @@ common: &common
port: 6379
keys:
key_pair_secret_key: 'key_pair_secret_key'
node_instruction_secret_key: 'node_instruction_secret_key'
airbrake_api_key: 'airbrake_api_key'
logentries_key: 'logentries_key'
secret_token: 'secret_token'

View File

@ -0,0 +1,12 @@
class CreateNodeInstructions < ActiveRecord::Migration
def change
create_table :node_instructions do |t|
t.integer :user_id, null: false
t.text :encrypted_instruction, null: false
t.text :output
t.string :status
t.timestamps
end
end
end

View File

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20140407181059) do
ActiveRecord::Schema.define(version: 20140414195426) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -287,6 +287,56 @@ ActiveRecord::Schema.define(version: 20140407181059) do
t.boolean "increase_release_tag", default: false, null: false
end
create_table "users", force: true do |t|
t.string "name"
t.string "email", default: "", null: false
t.string "encrypted_password", limit: 128, default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at"
t.datetime "updated_at"
t.text "ssh_key"
t.string "uname"
t.string "role"
t.string "language", default: "en"
t.integer "own_projects_count", default: 0, null: false
t.text "professional_experience"
t.string "site"
t.string "company"
t.string "location"
t.string "avatar_file_name"
t.string "avatar_content_type"
t.integer "avatar_file_size"
t.datetime "avatar_updated_at"
t.integer "failed_attempts", default: 0
t.string "unlock_token"
t.datetime "locked_at"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "authentication_token"
t.integer "build_priority", default: 50
t.boolean "sound_notifications", default: true
t.index ["authentication_token"], :name => "index_users_on_authentication_token"
t.index ["confirmation_token"], :name => "index_users_on_confirmation_token", :unique => true
t.index ["email"], :name => "index_users_on_email", :unique => true
t.index ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
t.index ["uname"], :name => "index_users_on_uname", :unique => true
t.index ["unlock_token"], :name => "index_users_on_unlock_token", :unique => true
end
create_table "node_instructions", force: true do |t|
t.integer "user_id", null: false
t.text "encrypted_instruction", null: false
t.text "output"
t.string "status"
t.datetime "created_at"
t.datetime "updated_at"
t.index ["user_id"], :name => "fk__node_instructions_user_id"
t.foreign_key ["user_id"], "users", ["id"], :on_update => :no_action, :on_delete => :no_action, :name => "fk_node_instructions_user_id"
end
create_table "platform_arch_settings", force: true do |t|
t.integer "platform_id", null: false
t.integer "arch_id", null: false
@ -530,43 +580,4 @@ ActiveRecord::Schema.define(version: 20140407181059) do
t.index ["subject_id", "subject_type"], :name => "index_tokens_on_subject_id_and_subject_type"
end
create_table "users", force: true do |t|
t.string "name"
t.string "email", default: "", null: false
t.string "encrypted_password", limit: 128, default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at"
t.datetime "updated_at"
t.text "ssh_key"
t.string "uname"
t.string "role"
t.string "language", default: "en"
t.integer "own_projects_count", default: 0, null: false
t.text "professional_experience"
t.string "site"
t.string "company"
t.string "location"
t.string "avatar_file_name"
t.string "avatar_content_type"
t.integer "avatar_file_size"
t.datetime "avatar_updated_at"
t.integer "failed_attempts", default: 0
t.string "unlock_token"
t.datetime "locked_at"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "authentication_token"
t.integer "build_priority", default: 50
t.boolean "sound_notifications", default: true
t.index ["authentication_token"], :name => "index_users_on_authentication_token"
t.index ["confirmation_token"], :name => "index_users_on_confirmation_token", :unique => true
t.index ["email"], :name => "index_users_on_email", :unique => true
t.index ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
t.index ["uname"], :name => "index_users_on_uname", :unique => true
t.index ["unlock_token"], :name => "index_users_on_unlock_token", :unique => true
end
end