Skip to content

Commit

Permalink
Merge 6c407a9 into 63c398d
Browse files Browse the repository at this point in the history
  • Loading branch information
LeonMatthes committed Apr 29, 2019
2 parents 63c398d + 6c407a9 commit 12cc03d
Show file tree
Hide file tree
Showing 9 changed files with 237 additions and 146 deletions.
2 changes: 1 addition & 1 deletion app/controllers/servers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def server_params
# `installed_software: []` permits arrays
params.require(:server).permit(:name, :cpu_cores, :ram_gb, :storage_gb, :ipv4_address,
:ipv6_address, :mac_address, :fqdn, {installed_software: []},
:model, :vendor, :description, :responsible_id)
:model, :vendor, :description, :responsible_id, sudo_user_ids: [], user_ids: [])
# Remove empty software form fields
# https://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-each_pair
params[:server].each { |k,v| v.reject!(&:blank?) if k.eql?('installed_software') }
Expand Down
92 changes: 92 additions & 0 deletions app/models/machine.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# frozen_string_literal: true

# Abstract superclass for Servers and VM objects
class Machine < ApplicationRecord
self.abstract_class = true

after_commit :save_users

attr_writer :sudo_users
attr_writer :users

def user_ids=(new_user_ids)
@users = User.find(new_user_ids)
end

def sudo_user_ids=(new_sudo_users)
@sudo_users = User.find(new_sudo_users)
end

# in this model, the groups: users, sudo_users, and responsible_users shall be seperate groups
# They will be merged for writing puppet scripts and seperated when reading them

def sudo_users
read_users if @sudo_users.nil?
@sudo_users
end

def users
read_users if @users.nil?
@users
end

def all_users
(users + sudo_users + responsible_users).uniq
end

def commit_message(git_writer)
if git_writer.added?
'Add ' + name
elsif git_writer.updated?
'Update ' + name
else
''
end
end

def node_script
Puppetscript.node_script(name, (sudo_users + responsible_users).uniq, all_users)
end

private

def read_users
begin
GitHelper.open_git_repository do
remote_users = Puppetscript.read_node_file(name)
@users = remote_users[:users] || [] if @users.nil?
@sudo_users = remote_users[:admins] || [] if @sudo_users.nil?
end
rescue Git::GitExecuteError, RuntimeError => e
Rails.logger.error(e)
# ensure users and sudo_users are always valid arrays
@users = [] if @users.nil?
@sudo_users = [] if @sudo_users.nil?
end
@users -= @sudo_users
@sudo_users -= responsible_users
end

def save_users
GitHelper.open_git_repository for_write: true do |git_writer|
name_script = Puppetscript.name_script name
write_puppetscripts git_writer, name_script, node_script
end
rescue Git::GitExecuteError, RuntimeError => e
Rails.logger.error(e)
# update local user assignments again to reflect the written status (if available)
@users = @sudo_users = nil
read_users
end

def write_puppetscripts(git_writer, name_script, node_script)
git_writer.write_file(Puppetscript.class_file_name(name), name_script)
git_writer.write_file(Puppetscript.node_file_name(name), node_script)
message = commit_message(git_writer)
git_writer.save(message)
end

def convert_to_user(user_or_id)
user.is_a? User ? user : User.find(user_or_id)
end
end
21 changes: 20 additions & 1 deletion app/models/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
# https://www.rubydoc.info/stdlib/resolv/Resolv
require 'resolv'

class Server < ApplicationRecord
class Server < Machine
belongs_to :responsible, class_name: :User

validates :name, :cpu_cores, :ram_gb, :storage_gb, :mac_address, :fqdn, :responsible_id, presence: true
validates :ipv4_address, presence: { unless: :ipv6_address? }
validates :ipv6_address, presence: { unless: :ipv4_address? }
Expand All @@ -15,6 +16,10 @@ class Server < ApplicationRecord
validates :ram_gb, numericality: { greater_than: 0 }
validates :storage_gb, numericality: { greater_than: 0 }

validates :name,
uniqueness: true,
length: { minimum: 1 },
format: { with: /\A[a-zA-Z0-9\-]+\z/, message: 'only allows letters, numbers and "-"' }
validates :ipv4_address, format: {
with: Resolv::IPv4::Regex,
message: 'is not a valid IPv4 address'
Expand All @@ -27,4 +32,18 @@ class Server < ApplicationRecord
with: /([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})/,
message: 'is not a valid MAC address'
}

# ActiveRecord defaults can't be used here, as the instance might not be saved
after_initialize :assign_defaults

# There is actually only ever one responsible user
# This method is a convenience accessor to allow for easier array concatination
# It is also recommended to use this method instead of :responsible because we might want to allow multiple responsible users in the future.
def responsible_users
responsible.nil? ? [] : [responsible]
end

def assign_defaults
self.name = '' if name.nil?
end
end
94 changes: 1 addition & 93 deletions app/models/virtual_machine_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,99 +3,7 @@
require './lib/puppetscript'
require './lib/git_helper'

class VirtualMachineConfig < ApplicationRecord
class VirtualMachineConfig < Machine
has_and_belongs_to_many :responsible_users, class_name: 'User'
belongs_to :project, optional: true

after_commit :save_users

attr_writer :sudo_users
attr_writer :users

def user_ids=(new_user_ids)
@users = User.find(new_user_ids)
end

def sudo_user_ids=(new_sudo_users)
@sudo_users = User.find(new_sudo_users)
end

# in this model, the groups: users, sudo_users, and responsible_users shall be seperate groups
# They will be merged for writing puppet scripts and seperated when reading them

def sudo_users
read_users if @sudo_users.nil?

@sudo_users
end

def users
read_users if @users.nil?

@users
end

def all_users
(users + sudo_users + responsible_users).uniq
end

def node_script
Puppetscript.node_script(name, (sudo_users + responsible_users).uniq, all_users)
end

private

def read_users
begin
GitHelper.open_git_repository do
remote_users = Puppetscript.read_node_file(name)
@users = remote_users[:users] || [] if @users.nil?
@sudo_users = remote_users[:admins] || [] if @sudo_users.nil?
end
rescue Git::GitExecuteError, RuntimeError => e
Rails.logger.error(e)
# ensure users and sudo_users are always valid arrays
@users = [] if @users.nil?
@sudo_users = [] if @sudo_users.nil?
end
@users -= @sudo_users
@sudo_users -= responsible_users
end

def convert_to_user(user_or_id)
user.is_a? User ? user : User.find(user_or_id)
end

def commit_message(git_writer)
if git_writer.added?
'Add ' + name
elsif git_writer.updated?
'Update ' + name
else
''
end
end

def write_puppetscripts(git_writer, name_script, node_script)
git_writer.write_file(Puppetscript.class_file_name(name), name_script)
git_writer.write_file(Puppetscript.node_file_name(name), node_script)
message = commit_message(git_writer)
git_writer.save(message)
end

def _save_users
GitHelper.open_git_repository for_write: true do |git_writer|
name_script = Puppetscript.name_script name
write_puppetscripts git_writer, name_script, node_script
end
rescue Git::GitExecuteError, RuntimeError => e
Rails.logger.error(e)
# update local user assignments again to reflect the written status (if available)
@users = @sudo_users = nil
read_users
end

def save_users
_save_users if @users || @sudo_users
end
end
127 changes: 88 additions & 39 deletions app/views/servers/_form.html.erb
Original file line number Diff line number Diff line change
@@ -1,51 +1,100 @@
<%# https://github.com/bootstrap-ruby/bootstrap_form %>
<%= bootstrap_form_with(model: server, local: true, layout: :horizontal) do |form| %>
<%= bootstrap_form_with(model: server, local: true) do |form| %>
<%# https://github.com/bootstrap-ruby/bootstrap_form#alert-messages %>
<%= form.alert_message "Please fix the errors below.", error_summary: false %>

<%= form.text_field :name %>
<%= form.text_area :description %>
<%# form.collection_select(method, collection, value_method, text_method, options = {}, html_options = {}) %>
<%= form.collection_select :responsible_id, User.all, :id, :human_readable_identifier,
options = {},
html_options = {multiple: false, class: 'selecttwo'} %>

<h5>Hardware Information</h5>
<%= form.text_field :vendor %>
<%= form.text_field :model %>
<%= form.number_field :cpu_cores, min: 0, label: 'CPU Cores' %>
<%= form.number_field :ram_gb, min: 0, label: 'RAM', append: 'GB' %>
<%= form.number_field :storage_gb, min: 0, label: 'Storage', append: 'GB' %>

<h5>Network Information</h5>
<%= form.text_field :ipv4_address, label: 'IPv4 Address' %>
<%= form.text_field :ipv6_address, label: 'IPv6 Address' %>
<%= form.text_field :mac_address, label: 'MAC Address' %>
<%= form.text_field :fqdn, label: 'Fully Qualified Domain Name (FQDN)' %>

<h5>Software Information</h5>

<script>
function addInput() {
$('<input/>', {
type: 'text', placeholder: 'Software',
class: 'form-control mb-1',
name: 'server[installed_software][]'
}).appendTo('#anchor');
}
</script>

<div class="form-group row">
<%= form.label :installed_software, "Installed Software", class:'col-form-label col-sm-2' %>
<div class="col-sm-10">
<div class="row border-bottom mb-4 pb-4">
<div class="col">
<h5>General Information</h5>
Please enter a short description of the Server and how you are planning to use it.
</div>
<div class="col-6">
<%= form.text_field :name %>
<%= form.text_area :description %>
</div>
</div>

<div class="row border-bottom mb-4 pb-4">
<div class="col">
<h5>User</h5>
Enter all users that need access to this server. If you can't find a user, that is most likely because they have
never logged into the HART system. Ask them to log in once so they are added to our list. You will be able to
change which users have access to your server at a later date. Make sure to enter yourself in the user list if you
need access.
</div>
<div class="col-6">
<%# form.collection_select(method, collection, value_method, text_method, options = {}, html_options = {}) %>
<%= form.collection_select :responsible_id, User.all, :id, :human_readable_identifier,
options = {selected: server.responsible_users.collect(&:id)},
html_options = {multiple: false, class: 'selecttwo'} %>
<%= form.collection_select :sudo_user_ids, User.all, :id, :human_readable_identifier,
options = {selected: server.sudo_users.collect(&:id),
include_hidden: false, # this must be false because otherwise an empty string will always be included in the post parameter
label: 'Users with sudo rights',
help: 'All responsible users will automatically be users with sudo rights.'},
html_options = {class: 'selecttwo', multiple: true} %>
<%= form.collection_select :user_ids, User.all, :id, :human_readable_identifier,
options = {selected: server.users.collect(&:id),
include_hidden: false, # this must be false because otherwise an empty string will always be included in the post parameter
label: 'Regular users'},
html_options = {class: 'selecttwo', multiple: true} %>
</div>
</div>

<div class="row border-bottom mb-4 pb-4">
<div class="col">
<h5>Hardware Information</h5>
You can select a Template or enter custom requirements. If you have special requirements or need an operating
system that is not in the list you can use the comment field at the bottom of this page.
</div>
<div class="col-6">
<%= form.text_field :vendor %>
<%= form.text_field :model %>
<%= form.number_field :cpu_cores, min: 0, label: 'CPU Cores' %>
<%= form.number_field :ram_gb, min: 0, label: 'RAM', append: 'GB' %>
<%= form.number_field :storage_gb, min: 0, label: 'Storage', append: 'GB' %>
</div>
</div>

<div class="row border-bottom mb-4 pb-4">
<div class="col">
<h5>Network Information</h5>
</div>
<div class="col-6">
<%= form.text_field :ipv4_address, label: 'IPv4 Address' %>
<%= form.text_field :ipv6_address, label: 'IPv6 Address' %>
<%= form.text_field :mac_address, label: 'MAC Address' %>
<%= form.text_field :fqdn, label: 'Fully Qualified Domain Name (FQDN)' %>
</div>
</div>

<div class="row border-bottom mb-4 pb-4">
<div class="col">
<h5>Software Information</h5>
</div>
<div class="col-6">

<script>
function addInput() {
$('<input/>', {
type: 'text', placeholder: 'Software',
class: 'form-control mb-1',
name: 'server[installed_software][]'
}).appendTo('#anchor');
}
</script>

<%= form.label :installed_software, "Installed Software" %>
<% server.installed_software.each do |software| %>
<%= form.text_field_without_bootstrap :installed_software,
multiple: true, value: software, hide_label: true, class:'form-control mb-1' %>
<%= form.text_field :installed_software,
multiple: true, value: software, hide_label: true, class: 'form-control mb-1' %>
<% end %>
<span id="anchor"></span>
<div id="anchor"></div>
<input type="button" class="btn btn-secondary" onclick="addInput()" value="Add Software" />
</div>
</div>

<%= form.submit class: "btn btn-primary" %>
<%= link_to 'Back', server, class: 'btn btn-secondary' if server.persisted? %>
<% end %>
3 changes: 0 additions & 3 deletions app/views/servers/edit.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
<h1>Editing Server</h1>

<%= render 'form', server: @server %>
<%= link_to 'Show', @server %> |
<%= link_to 'Back', servers_path %>
Loading

0 comments on commit 12cc03d

Please sign in to comment.