Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support editing groups with modify commands #110

Merged
merged 24 commits into from
Mar 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions lib/inventoryware/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,17 @@ def cli_syntax(command, args_str = nil)

def add_multi_node_options(command)
command.option '--all', "Select all assets"
command.option '-g', '--group GROUP',
"Select assets in GROUP, specify commma-separated list for multiple groups"
add_group_option(command)
end

def add_create_option(command)
command.option '-c', '--create',
"Create specified asset(s) if they don't exist"
"Create specified asset(s) if they don't exist"
end

def add_group_option(command)
command.option '-g', '--group GROUP',
"Select assets in GROUP, specify comma-separated list for multiple groups"
end
end

Expand Down Expand Up @@ -125,25 +129,27 @@ def add_create_option(command)
end

command :'modify map' do |c|
cli_syntax(c, 'ASSET')
c.description = "Modify mapping data for an asset"
cli_syntax(c, '[ASSET_SPEC]')
c.description = "Modify mapping data for one or more assets"
c.hidden = true
add_multi_node_options(c)
add_create_option(c)
action(c, Commands::Modifys::Map)
end

command :'modify notes' do |c|
cli_syntax(c, 'ASSET')
c.description = "Modify miscellaneous notes for an asset"
cli_syntax(c, '[ASSET_SPEC]')
c.description = "Modify miscellaneous notes for one or more assets"
c.hidden = true
add_multi_node_options(c)
add_create_option(c)
action(c, Commands::Modifys::Notes)
end

command :list do |c|
cli_syntax(c)
c.description = "List all assets that have stored data"
add_multi_node_options(c)
add_group_option(c)
action(c, Commands::List)
end

Expand Down
22 changes: 9 additions & 13 deletions lib/inventoryware/commands/delete.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,17 @@ module Inventoryware
module Commands
class Delete < MultiNodeCommand
def run
node_locations = find_nodes()
nodes = fetch_nodes()

unless node_locations.empty?
prefix = "You are about to delete"
node_locations.map! { |loc| File.expand_path(loc) }
if node_locations.length > 1
node_msg = "#{prefix}:\n#{node_locations.join("\n")}\nProceed? (y/n)"
else
node_msg = "#{prefix} #{node_locations[0]} - proceed? (y/n)"
end
if $terminal.agree(node_msg)
node_locations.each { |node| FileUtils.rm node }
end
prefix = "You are about to delete"
node_paths = nodes.map { |n| File.expand_path(n.path) }
if node_paths.length > 1
node_msg = "#{prefix}:\n#{node_paths.join("\n")}\nProceed? (y/n)"
else
puts "No assets found"
node_msg = "#{prefix} #{node_paths[0]} - proceed? (y/n)"
end
if $terminal.agree(node_msg)
node_paths.each { |path| FileUtils.rm path }
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/inventoryware/commands/edit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def action(node)
node.save
# maybe don't create unless saved? i.e. don't create the file above
# instead save as closing
TTY::Editor.open(node.location, command: :rvim)
TTY::Editor.open(node.path, command: :rvim)
end
end
end
Expand Down
5 changes: 3 additions & 2 deletions lib/inventoryware/commands/list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@
# ==============================================================================
require 'inventoryware/command'
require 'inventoryware/config'
require 'inventoryware/node'

module Inventoryware
module Commands
class List < MultiNodeCommand
class List < Command
def run
files = if @options.group
find_nodes_in_groups(@options.group.split(','))
Node.find_nodes_in_groups(@options.group.split(','))
else
Dir.glob(File.join(Config.yaml_dir, '*.yaml'))
end
Expand Down
5 changes: 1 addition & 4 deletions lib/inventoryware/commands/modifys/groups.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,7 @@ def run

group = @argv[0]

find_nodes("group").each do |location|
node = Node.new(location)
type = Utils.get_new_asset_type if @options.create
node.create_if_non_existent(type)
fetch_nodes("group").each do |node|
if @options.primary
node.data['mutable']['primary_group'] = group
else
Expand Down
30 changes: 20 additions & 10 deletions lib/inventoryware/commands/modifys/map.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,31 @@
# For more information on Flight Inventory, please visit:
# https://github.com/openflighthpc/flight-inventory
# ==============================================================================
require 'inventoryware/commands/single_node_command'
require 'inventoryware/commands/multi_node_command'
require 'inventoryware/exceptions'
require 'inventoryware/node'

module Inventoryware
module Commands
module Modifys
class Map < SingleNodeCommand
def action(node)
class Map < MultiNodeCommand
def run
nodes = fetch_nodes()
node = nodes.first

prompt = TTY::Prompt.new
unless prompt.no?('Would you like to add map metadata? (Default: No)')
get_map_metadata_from_user(node, prompt)
get_map_metadata_from_user(nodes, prompt)
end

map = map_to_string(node.data['mutable']['map'])
map = string_to_map(edit_with_tmp_file(map, :"rvim +'set number'"))
node.data['mutable']['map'] = map
node.save
map = string_to_map(Utils.edit_with_tmp_file(map,
:"rvim +'set number'"))

nodes.each do |node|
node.data['mutable']['map'] = map
node.save
end
end

# takes a hash with numerical keys
Expand Down Expand Up @@ -74,7 +82,7 @@ def string_to_map(str)
return map
end

def get_map_metadata_from_user(node, prompt)
def get_map_metadata_from_user(nodes, prompt)
prompt.say('Enter integer values for the dimensions of the map:')

x = prompt.ask('X:') do |q|
Expand All @@ -90,8 +98,10 @@ def get_map_metadata_from_user(node, prompt)
%w(DownRight RightDown RightUp UpRight)
)

node.data['mutable']['map_dimensions'] = "#{x}x#{y}"
node.data['mutable']['map_pattern'] = pattern
nodes.each do |node|
node.data['mutable']['map_dimensions'] = "#{x}x#{y}"
node.data['mutable']['map_pattern'] = pattern
end
end
end
end
Expand Down
19 changes: 13 additions & 6 deletions lib/inventoryware/commands/modifys/notes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,24 @@
# For more information on Flight Inventory, please visit:
# https://github.com/openflighthpc/flight-inventory
# ==============================================================================
require 'inventoryware/commands/single_node_command'
require 'inventoryware/commands/multi_node_command'
require 'inventoryware/node'

module Inventoryware
module Commands
module Modifys
class Notes < SingleNodeCommand
def action(node)
class Notes < MultiNodeCommand
def run
nodes = fetch_nodes()
node = nodes.first

notes = node.data['mutable'].fetch('notes', '')
notes = edit_with_tmp_file(notes, :rvim).strip
node.data['mutable']['notes'] = notes
node.save
notes = Utils.edit_with_tmp_file(notes, :rvim).strip

nodes.each do |node|
node.data['mutable']['notes'] = notes
node.save
end
end
end
end
Expand Down
5 changes: 1 addition & 4 deletions lib/inventoryware/commands/modifys/other.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,7 @@ def run
ERROR
end

find_nodes("modification").each do |location|
node = Node.new(location)
type = Utils.get_new_asset_type if @options.create
node.create_if_non_existent(type)
fetch_nodes("modification").each do |node|
if value
node.data['mutable'][field] = value
else
Expand Down
102 changes: 20 additions & 82 deletions lib/inventoryware/commands/multi_node_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,29 @@
# ==============================================================================
require 'inventoryware/command'
require 'inventoryware/exceptions'
require 'inventoryware/utils'
require 'inventoryware/node'

require 'nodeattr_utils'

module Inventoryware
module Commands
class MultiNodeCommand < Command
def find_nodes(*args)
def fetch_nodes(*args)
resolve_node_options(@argv, @options, args)

nodes = @argv[args.length]

node_locations = locate_nodes(nodes, @options)
node_paths = find_nodes(nodes, @options)
node_paths = node_paths.uniq
nodes = node_paths.map { |p| Node.new(p) }
if @options.create
new_nodes = nodes.select { |n| not File.file?(n.path) }
unless new_nodes.empty?
type = Utils.get_new_asset_type
new_nodes.each { |n| n.create_if_non_existent(type) }
end
end
return nodes
end

private
Expand All @@ -64,97 +74,25 @@ def resolve_node_options(argv, options, other_args)

# given a set of nodes and relevant options returns an expanded list
# of all the necessary nodes
def locate_nodes(nodes, options)
def find_nodes(nodes, options)
node_locations = []
if options.all
node_locations = find_all_nodes
node_locations = Node.find_all_nodes
else
if nodes
node_locations.push(*find_single_nodes(nodes, !!options.create))
node_locations.push(*Node.find_single_nodes(nodes, !!options.create))
end
if options.group
node_locations.push(*find_nodes_in_groups(options.group.split(',')))
node_locations.push(*Node.find_nodes_in_groups(options.group.split(',')))
end
end
return node_locations
end

# retrieves all .yaml files in the storage dir
def find_all_nodes()
node_locations = Dir.glob(File.join(Config.yaml_dir, '*.yaml'))
if node_locations.empty?
$stderr.puts "No asset data found "\
"in #{File.expand_path(Config.yaml_dir)}"
end
return node_locations
end

# retreives all nodes in the given groups
# this quite an intensive method of way to go about searching the yaml
# each file is converted to a sting and then searched
# seems fine as it stands but if speed becomes an issue could stand to
# be changed
def find_nodes_in_groups(groups)
nodes = []
find_all_nodes().each do |location|
found = []
File.open(location) do |file|
contents = file.read
m = contents.match(/primary_group: (.*?)$/)
found.append(m[1]) if m
m = contents.match(/secondary_groups: (.*?)$/)
found = found + (m[1].split(',')) if m
end
unless (found & groups).empty?
nodes.append(location)
end
end
if nodes.empty?
$stderr.puts "No assets found in #{groups.join(' or ')}."
end
return nodes
end

# retreives the .yaml file for each of the given nodes
# expands node ranges if they exist
# if return missing is passed, returns paths to the .yamls of non-existent
# nodes
def find_single_nodes(node_str, return_missing = false)
nodes = expand_asterisks(NodeattrUtils::NodeParser.expand(node_str))
$stderr.puts "No assets found for '#{node_str}'" if nodes.empty?
node_locations = []
nodes.each do |node|
node_yaml = "#{node}.yaml"
node_yaml_location = File.join(Config.yaml_dir, node_yaml)
unless Utils.check_file_readable?(node_yaml_location)
$stderr.puts "File #{node_yaml} not found within "\
"#{File.expand_path(Config.yaml_dir)}"
if return_missing
$stderr.puts "Creating..."
else
$stderr.puts "Skipping."
next
end
end
node_locations.append(node_yaml_location)
raise ArgumentError, <<-ERROR.chomp
No assets found
ERROR
end
return node_locations
end

def expand_asterisks(nodes)
new_nodes = []
nodes.each do |node|
if node.match(/\*/)
node_names = Dir.glob(File.join(Config.yaml_dir, node)).map { |file|
File.basename(file, '.yaml')
}
new_nodes.push(*node_names)
end
end
nodes.delete_if { |node| node.match(/\*/) }
nodes.push(*new_nodes)
return nodes
end
end
end
end
2 changes: 1 addition & 1 deletion lib/inventoryware/commands/shows/data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ module Commands
module Shows
class Data < SingleNodeCommand
def action(node)
File.open(node.location) do |file|
File.open(node.path) do |file|
puts file.read
end
end
Expand Down
Loading