Class: Onceover::CLI::Run::Diff

Inherits:
Object
  • Object
show all
Defined in:
lib/onceover/octocatalog/diff/cli.rb

Class Method Summary collapse

Class Method Details

.commandObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/onceover/octocatalog/diff/cli.rb', line 5

def self.command
  @cmd ||= Cri::Command.define do
    name 'diff'
    usage 'diff'
    summary "Diff two versions of the controlrepo's compiled catalogs"
    description <<-DESCRIPTION
This uses octocatalog-diff to run diffs on all things in the test matrix
instead of actually testing them. Requires two branches, tags or
revisions to compare between.
    DESCRIPTION

    option :f,  :from, 'branch to compare from', argument: :required
    option :t,  :to,   'branch to compare to', argument: :required

    run do |opts, args, cmd|
      require 'pry'
      require 'facter'
      require 'colored'

      #TODO: Allow for custom arguments
      repo        = Onceover::Controlrepo.new(opts)
      test_config = Onceover::TestConfig.new(repo.onceover_yaml, opts)
      num_threads = (Facter.value('processors')['count'] / 2)
      tests = test_config.run_filters(Onceover::Test.deduplicate(test_config.spec_tests))

      @queue = tests.inject(Queue.new, :push)
      @results = []

      @threads = Array.new(num_threads) do
        Thread.new do
          r10k_cache_dir = Dir.mktmpdir('r10k_cache')
          r10k_config = {
            'cachedir' => r10k_cache_dir,
          }
          logger.debug "Creating r10k cache for thread at #{r10k_cache_dir}"
          File.write("#{r10k_cache_dir}/r10k.yaml",r10k_config.to_yaml)

          until @queue.empty?
            test = @queue.shift

            logger.info "Preparing environment for #{test.classes[0].name} on #{test.nodes[0].name}"
            logger.debug "Creating temp directory"
            tempdir = Dir.mktmpdir(test.to_s)
            logger.debug "Temp directory created at #{tempdir}"

            logger.debug "Copying controlrepo to #{tempdir}"
            FileUtils.copy_entry(repo.root,tempdir)

            logger.debug "Converting facts to yaml"
            Onceover::Octocatalog::Diff.create_facts_yaml(repo,"#{tempdir}/spec/factsets")

            logger.info "Deploying Puppetfile for #{test.classes[0].name} on #{test.nodes[0].name}"
            r10k_cmd = "r10k puppetfile install --verbose --color --puppetfile #{repo.puppetfile} --config #{r10k_cache_dir}/r10k.yaml"
            Open3.popen3(r10k_cmd) do |stdin, stdout, stderr, wait_thr|
              exit_status = wait_thr.value
              if exit_status.exitstatus != 0
                STDOUT.puts stdout.read
                STDERR.puts stderr.read
                abort "R10k encountered an error, see the logs for details"
              end
            end

            # TODO: Improve the way this works so that it doesn't blat site.pp
            logger.debug "Creating before script that overwrites site.pp"
            class_name = test.classes[0].name
            template_dir = File.expand_path('../../../../templates',File.dirname(__FILE__))
            template = File.read(File.expand_path("./change_manifest.rb.erb",template_dir))
            File.write("#{tempdir}/bootstrap_script.rb",ERB.new(template, nil, '-').result(binding))
            FileUtils.chmod("u=rwx","#{tempdir}/bootstrap_script.rb")

            logger.debug "Getting Puppet binary"
            binary = `which puppet`.chomp

            logger.debug "Running Octocatalog diff"
            logger.debug "Command: octocatalog-diff --fact-file #{tempdir}/spec/factsets/#{test.nodes[0].name}.yaml -f #{opts[:from]} -t #{opts[:to]} --basedir #{tempdir} --puppet-binary #{binary} --bootstrap-script #{tempdir}/bootstrap_script.rb"
            logger.info "Compiling catalogs for #{test.classes[0].name} on #{test.nodes[0].name}"
            cmd = "octocatalog-diff --fact-file #{tempdir}/spec/factsets/#{test.nodes[0].name}.yaml -f #{opts[:from]} -t #{opts[:to]} --basedir #{tempdir} --puppet-binary #{binary} --bootstrap-script '#{tempdir}/bootstrap_script.rb'"
            Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
              exit_status = wait_thr.value
              @results << {
                stdout: stdout.read,
                stderr: stderr.read,
                exit_status: exit_status.exitstatus,
                test: test
              }
            end
            logger.info "Storing results for #{test.classes[0].name} on #{test.nodes[0].name}"
            FileUtils.rm_r(tempdir)
          end

          FileUtils.rm_r(r10k_cache_dir)
        end
      end

      @threads.each(&:join)
      @results.each do |result|
        puts "#{"Test:".bold} #{result[:test].classes[0].name} on #{result[:test].nodes[0].name}"
        puts "#{"Exit:".bold} #{result[:exit_status]}"
        puts "#{"Status:".bold} #{"changes".yellow}" if result[:exit_status] == 2
        puts "#{"Status:".bold} #{"no differences".green}" if result[:exit_status] == 0
        puts "#{"Status:".bold} #{"failed".red}" if result[:exit_status] == 1
        puts "#{"Results:".bold}\n#{result[:stdout]}\n" if result[:exit_status] == 2
        puts "#{"Errors:".bold}\n#{result[:stderr]}\n" if result[:exit_status] == 1
        puts ""
      end
    end
  end
end