File: setup.rb

package info (click to toggle)
ruby-rspec-puppet 2.9.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,416 kB
  • sloc: ruby: 6,661; makefile: 6
file content (213 lines) | stat: -rw-r--r-- 5,794 bytes parent folder | download | duplicates (2)
1
2
3
4
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
require 'puppet'
require 'fileutils'

begin
  require 'win32/dir'
rescue LoadError
  nil
end

module RSpec::Puppet
  class Setup
    def self.run(module_name=nil)
      unless is_module_dir?
        $stderr.puts "Does not appear to be a Puppet module.  Aborting"
        return false
      end

      if control_repo?
        $stderr.puts <<-END
Unable to find a metadata.json file. If this is a module, please create a
metadata.json file and try again.
END
        return false
      end

      safe_setup_directories(module_name)
      safe_touch(File.join('spec', 'fixtures', 'manifests', 'site.pp'))

      safe_create_spec_helper
      safe_create_rakefile
    end

    def self.safe_setup_directories(module_name=nil, verbose=true)
      if control_repo?
        $stderr.puts "Unable to setup rspec-puppet automatically in a control repo" if verbose
        return false
      end

      if module_name.nil?
        module_name = get_module_name
        if module_name.nil?
          $stderr.puts "Unable to determine module name.  Aborting" if verbose
          return false
        end
      end

      [
        'spec',
        File.join('spec', 'classes'),
        File.join('spec', 'defines'),
        File.join('spec', 'functions'),
        File.join('spec', 'hosts'),
        File.join('spec', 'fixtures'),
        File.join('spec', 'fixtures', 'manifests'),
        File.join('spec', 'fixtures', 'modules'),
      ].each { |dir| safe_mkdir(dir, verbose) }

      target = File.join('spec', 'fixtures', 'modules', module_name)
      safe_make_link('.', target, verbose)
    end

    def self.safe_teardown_links(module_name=nil)
      if module_name.nil?
        module_name = get_module_name
        if module_name.nil?
          $stderr.puts "Unable to determine module name.  Aborting"
          return false
        end
      end

      target = File.join('spec', 'fixtures', 'modules', module_name)
      if File.symlink?(target) && File.readlink(target) == File.expand_path('.')
        File.unlink(target)
      end
    end
  protected
    def self.control_repo?
      !File.exist?('metadata.json')
    end

    def self.get_module_name
      module_name = nil
      Dir["manifests/*.pp"].entries.each do |manifest|
        module_name = get_module_name_from_file(manifest)
        break unless module_name.nil?
      end
      module_name
    end

    def self.get_module_name_from_file(file)
      # FIXME: see discussion at
      # https://github.com/rodjek/rspec-puppet/issues/290
      if Puppet.version.to_f >= 4.0 || RSpec.configuration.parser == 'future'
        require 'puppet/pops'
        p = Puppet::Pops::Parser::Lexer2.new
      else
        p = Puppet::Parser::Lexer.new
      end
      module_name = nil
      p.string = File.read(file)
      tokens = p.fullscan

      i = tokens.index { |token| [:CLASS, :DEFINE].include? token.first }
      unless i.nil?
        module_name = tokens[i + 1].last[:value].split('::').first
      end

      module_name
    end

    def self.is_module_dir?
      Dir["*"].entries.include? "manifests"
    end

    def self.safe_mkdir(dir, verbose=true)
      if File.exist? dir
        unless File.directory? dir
          $stderr.puts "!! #{dir} already exists and is not a directory"
        end
      else
        begin
          FileUtils.mkdir dir
        rescue Errno::EEXIST => e
          raise e unless File.directory? dir
        end
        puts " + #{dir}/" if verbose
      end
    end

    def self.safe_touch(file)
      if File.exist? file
        unless File.file? file
          $stderr.puts "!! #{file} already exists and is not a regular file"
        end
      else
        FileUtils.touch file
        puts " + #{file}"
      end
    end

    def self.safe_create_file(filename, content)
      if File.exist? filename
        old_content = File.read(filename)
        if old_content != content
          $stderr.puts "!! #{filename} already exists and differs from template"
        end
      else
        File.open(filename, 'w') do |f|
          f.puts content
        end
        puts " + #{filename}"
      end
    end

    def self.safe_create_spec_helper
      content = File.read(File.expand_path(File.join(__FILE__, '..', 'spec_helper.rb')))
      safe_create_file('spec/spec_helper.rb', content)
    end

    def self.link_to_source?(target, source)
      return false unless link?(target)

      link_target = Dir.respond_to?(:read_junction) ? Dir.read_junction(target) : File.readlink(target)

      link_target == File.expand_path(source)
    end

    def self.link?(target)
      Dir.respond_to?(:junction?) ? Dir.junction?(target) : File.symlink?(target)
    end

    def self.safe_make_link(source, target, verbose=true)
      if File.exist?(target) && !link?(target)
        $stderr.puts "!! #{target} already exists and is not a symlink"
        return
      end

      return if link_to_source?(target, source)

      if Puppet::Util::Platform.windows?
        output = `call mklink /J "#{target.gsub('/', '\\')}" "#{source}"`
        unless $?.success?
          puts output
          abort
        end
      else
        begin
          FileUtils.ln_s(File.expand_path(source), target)
        rescue Errno::EEXIST => e
          raise e unless link_to_source?(target, source)
        end
      end
      puts " + #{target}" if verbose
    end

    def self.safe_create_rakefile
      content = <<-'EOF'
require 'rspec-puppet/rake_task'

begin
  if Gem::Specification::find_by_name('puppet-lint')
    require 'puppet-lint/tasks/puppet-lint'
    PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "vendor/**/*.pp"]
    task :default => [:rspec, :lint]
  end
rescue Gem::LoadError
  task :default => :rspec
end
EOF
      safe_create_file('Rakefile', content)
    end
  end
end