File: setup.rb

package info (click to toggle)
ruby-rspec-puppet 4.0.2%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,444 kB
  • sloc: ruby: 6,377; makefile: 6
file content (202 lines) | stat: -rw-r--r-- 5,575 bytes parent folder | download
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
# frozen_string_literal: true

require 'English'
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?
        warn 'Does not appear to be a Puppet module.  Aborting'
        return false
      end

      if control_repo?
        warn <<~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?
        warn '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?
          warn '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?
          warn 'Unable to determine module name.  Aborting'
          return false
        end
      end

      target = File.join('spec', 'fixtures', 'modules', module_name)
      return unless File.symlink?(target) && File.readlink(target) == File.expand_path('.')

      File.unlink(target)
    end

    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)
      require 'puppet/pops'
      p = Puppet::Pops::Parser::Lexer2.new
      module_name = nil
      p.string = File.read(file)
      tokens = p.fullscan

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

      module_name
    end

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

    def self.safe_mkdir(dir, verbose = true)
      if File.exist? dir
        warn "!! #{dir} already exists and is not a directory" unless File.directory? dir
      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
        warn "!! #{file} already exists and is not a regular file" unless File.file? file
      else
        FileUtils.touch file
        puts " + #{file}"
      end
    end

    def self.safe_create_file(filename, content)
      if File.exist? filename
        old_content = File.read(filename)
        warn "!! #{filename} already exists and differs from template" if old_content != content
      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)
        warn "!! #{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.tr('/', '\\')}" "#{source}"`
        unless $CHILD_STATUS.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