From 6f221b512cd2cbdf58a590f08479c6580698ae39 Mon Sep 17 00:00:00 2001 From: Tom McKay Date: Tue, 1 Sep 2015 17:21:10 -0400 Subject: [PATCH] + hosts export w/ organization + export / import puppet facts + added examples dir + subscriptions can have optional Organization column to be filled w/ --organization + content-view-filters export date based errata + read from http/file/stdin + removed gettext from gemspec (prevented installation) --- examples/RHEL_Releases/subscriptions.csv | 3 ++ hammer_cli_csv.gemspec | 5 +- lib/hammer_cli_csv/base.rb | 5 +- lib/hammer_cli_csv/content_view_filters.rb | 10 +++- lib/hammer_cli_csv/hosts.rb | 6 ++- lib/hammer_cli_csv/puppet_facts.rb | 61 ++++++++++++---------- lib/hammer_cli_csv/subscriptions.rb | 3 ++ 7 files changed, 59 insertions(+), 34 deletions(-) create mode 100644 examples/RHEL_Releases/subscriptions.csv diff --git a/examples/RHEL_Releases/subscriptions.csv b/examples/RHEL_Releases/subscriptions.csv new file mode 100644 index 0000000..b85fc95 --- /dev/null +++ b/examples/RHEL_Releases/subscriptions.csv @@ -0,0 +1,3 @@ +Name,Count,Organization,Manifest File,Content Set,Arch,Release +Red Hat Enterprise Linux Server,1,,,Red Hat Enterprise Linux 7 Server (RPMs),x86_64,7Server +Red Hat Enterprise Linux Server,1,,,Red Hat Enterprise Linux 6 Server (RPMs),x86_64,6Server \ No newline at end of file diff --git a/hammer_cli_csv.gemspec b/hammer_cli_csv.gemspec index 2b869a6..5ba1121 100644 --- a/hammer_cli_csv.gemspec +++ b/hammer_cli_csv.gemspec @@ -6,10 +6,10 @@ Gem::Specification.new do |spec| spec.name = "hammer_cli_csv" spec.version = HammerCLICsv.version - spec.authors = ["Tom McKay"] + spec.authors = ["Thomas McKay"] spec.email = ["thomasmckay@redhat.com"] spec.homepage = "http://github.com/Katello/hammer-cli-csv" - spec.license = "GPL-2" + spec.license = "GPL-3" spec.platform = Gem::Platform::RUBY spec.summary = "CSV commands for Hammer" @@ -20,7 +20,6 @@ Gem::Specification.new do |spec| spec.require_paths = %w(lib) spec.add_dependency('hammer_cli_katello') - spec.add_dependency("gettext", "~> 2.0") spec.add_development_dependency("rubocop", "0.24.1") end diff --git a/lib/hammer_cli_csv/base.rb b/lib/hammer_cli_csv/base.rb index bad03d3..d267448 100644 --- a/lib/hammer_cli_csv/base.rb +++ b/lib/hammer_cli_csv/base.rb @@ -1,6 +1,7 @@ require 'apipie-bindings' require 'hammer_cli' require 'json' +require 'open-uri' require 'csv' require 'hammer_cli_csv/csv' @@ -105,11 +106,11 @@ def labelize(name) def thread_import(return_headers = false, filename=nil, name_column=nil) filename ||= option_file || '/dev/stdin' csv = [] - CSV.foreach(filename, { + CSV.new(open(filename), { :skip_blanks => true, :headers => :first_row, :return_headers => return_headers - }) do |line| + }).each do |line| csv << line end lines_per_thread = csv.length / option_threads.to_i + 1 diff --git a/lib/hammer_cli_csv/content_view_filters.rb b/lib/hammer_cli_csv/content_view_filters.rb index ae0a516..e8f5b86 100644 --- a/lib/hammer_cli_csv/content_view_filters.rb +++ b/lib/hammer_cli_csv/content_view_filters.rb @@ -50,11 +50,19 @@ def export end rules.delete!("\n") when /erratum/ + rules = CSV.generate do |column| + rule = filter['rules'][0] + conditions = [] + conditions << "start = #{DateTime.parse(rule['start_date']).strftime('%F')}" if rule['start_date'] + conditions << "end = #{DateTime.parse(rule['end_date']).strftime('%F')}" if rule['end_date'] + conditions += rule['types'] + column << conditions + end + rules.delete!("\n") when /package_group/ else raise "Unknown filter rule type '#{filter['type']}'" end - #puts "#{filter['type']} -> #{rule}" name = contentview['name'] repositories = export_column(filter, 'repositories', 'name') diff --git a/lib/hammer_cli_csv/hosts.rb b/lib/hammer_cli_csv/hosts.rb index 7dbe920..7ae65ec 100644 --- a/lib/hammer_cli_csv/hosts.rb +++ b/lib/hammer_cli_csv/hosts.rb @@ -16,7 +16,9 @@ class HostsCommand < BaseCommand def export CSV.open(option_file || '/dev/stdout', 'wb', {:force_quotes => true}) do |csv| csv << [NAME, COUNT, ORGANIZATION, LOCATION, ENVIRONMENT, OPERATINGSYSTEM, ARCHITECTURE, MACADDRESS, DOMAIN, PARTITIONTABLE] - @api.resource(:hosts).call(:index, {:per_page => 999999})['results'].each do |host| + search_options = {:per_page => 999999} + search_options['search'] = "organization = #{option_organization}" if option_organization + @api.resource(:hosts).call(:index, search_options)['results'].each do |host| host = @api.resource(:hosts).call(:show, {'id' => host['id']}) raise "Host 'id=#{host['id']}' not found" if !host || host.empty? @@ -47,6 +49,8 @@ def import end def create_hosts_from_csv(line) + return if option_organization && line[ORGANIZATION] != option_organization + line[COUNT].to_i.times do |number| name = namify(line[NAME], number) if !@existing.include? name diff --git a/lib/hammer_cli_csv/puppet_facts.rb b/lib/hammer_cli_csv/puppet_facts.rb index 204eae4..d0f5dfa 100644 --- a/lib/hammer_cli_csv/puppet_facts.rb +++ b/lib/hammer_cli_csv/puppet_facts.rb @@ -4,50 +4,57 @@ class PuppetFactsCommand < BaseCommand command_name 'puppet-facts' desc 'import or export puppet facts' + ORGANIZATION = 'Organization' + FACTS = 'Puppet Facts' + + SEPARATOR = ' = ' + def export CSV.open(option_file || '/dev/stdout', 'wb', {:force_quotes => true}) do |csv| - headers = [NAME, COUNT] - # Extracted facts are always based upon the first host found, otherwise this would be an intensive - # method to gather all the possible column names - any_host = @api.resource(:hosts).call(:index, {:per_page => 1})['results'][0] - headers += @api.resource(:puppetfactss).call(:index, { - 'host_id' => any_host['name'], - 'per_page' => 999999 - })['results'][any_host['name']].keys - csv << headers + csv << [NAME, COUNT, ORGANIZATION, FACTS] - @api.resource(:hosts).call(:index, {:per_page => 999999})['results'].each do |host| - line = [host['name'], 1] - facts = @api.resource(:puppetfactss).call(:index, {'host_id' => host['name'], 'per_page' => 999999})[host['name']] + search_options = {:per_page => 999999} + search_options['search'] = "organization = #{option_organization}" if option_organization + @api.resource(:hosts).call(:index, search_options)['results'].each do |host| + facts = @api.resource(:fact_values).call(:index, { + 'search' => "host = #{host['name']}", + 'per_page' => 999999 + })['results'] + facts = @api.resource(:fact_values).call(:index, { + 'search' => "host = #{host['name']}", + 'per_page' => 999999 + })['results'][host['name']] facts ||= {} - headers[2..-1].each do |fact_name| - line << facts[fact_name] || '' + + values = CSV.generate do |column| + column << facts.collect do |fact_name, fact_value| + "#{fact_name}#{SEPARATOR}#{fact_value}" + end end - csv << line + values.delete!("\n") + + csv << [host['name'], 1, host['organization_name'], values] end end end def import - @headers = nil - thread_import(true) do |line| create_puppetfacts_from_csv(line) end end def create_puppetfacts_from_csv(line) - if @headers.nil? - @headers = line - return - end + return if option_organization && line[ORGANIZATION] != option_organization line[COUNT].to_i.times do |number| name = namify(line[NAME], number) print "Updating puppetfacts '#{name}'..." if option_verbose? - facts = line.to_hash - facts.delete(NAME) - facts.delete(COUNT) + facts = {} + collect_column(line[FACTS]) do |fact| + (fact_name, fact_value) = fact.split(SEPARATOR) + facts[fact_name] = fact_value + end # Namify the values if the host name was namified if name != line[NAME] @@ -57,9 +64,9 @@ def create_puppetfacts_from_csv(line) end @api.resource(:hosts).call(:facts, { - 'name' => name, - 'facts' => facts - }) + 'name' => name, + 'facts' => facts + }) print "done\n" if option_verbose? end rescue RuntimeError => e diff --git a/lib/hammer_cli_csv/subscriptions.rb b/lib/hammer_cli_csv/subscriptions.rb index 232e66d..a132127 100644 --- a/lib/hammer_cli_csv/subscriptions.rb +++ b/lib/hammer_cli_csv/subscriptions.rb @@ -52,6 +52,9 @@ def import end def enable_products_from_csv(line) + organization = line[ORGANIZATION] || option_organization + raise "Organization is required in either input CSV or by option --organization" if organization.nil? || organization.empty? + line[ORGANIZATION] = organization return if option_organization && line[ORGANIZATION] != option_organization results = @api.resource(:products).call(:index, {