Class: Vtasks::Puppet

Inherits:
Rake::TaskLib
  • Object
show all
Includes:
Utils::Git, Utils::Output
Defined in:
lib/vtasks/puppet.rb

Overview

Puppet tasks

Constant Summary

Constants included from Utils::Git

Utils::Git::GITHUB_TOKEN

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Utils::Output

#debug, #error, #info, #warn

Methods included from Utils::Git

#git_branch, #git_ci_status, #git_clean_repo, #git_commit, #git_url

Constructor Details

#initialize(options = {}) ⇒ Puppet

Returns a new instance of Puppet.



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
# File 'lib/vtasks/puppet.rb', line 18

def initialize(options = {})
  # Fix for namespaced :syntax task
  task syntax: ['puppet:syntax']

  namespace :puppet do
    begin
      require 'r10k/cli'
      require 'r10k/puppetfile'
      require 'puppet_forge'
      require 'puppetlabs_spec_helper/rake_tasks' # ORDER IS VERY IMPORTANT BECAUSE IT OVERRIDES A LOT OF OTHER TASKS; AS OF NOW IT NEEDS TO BE AFTER `r10k` and `puppet_forge` (BECAUSE OF FAST_GETTEXT INITIALIZATION) BUT BEFORE puppet-strings (BECAUSE ERROR: `Don't know how to build task 'spec_prep'`)
      require 'metadata-json-lint/rake_task'
      require 'puppet-syntax/tasks/puppet-syntax'
      require 'puppet-lint/tasks/puppet-lint'
      require 'puppet-strings/tasks'
      require 'puppet_blacksmith/rake_tasks'
    rescue LoadError
      nil # Might be in a group that is not installed
    end

    @exclude_paths ||= options.fetch(
      :exclude_paths,
      [
        'bundle/**/*',
        'modules/**/*',
        'pkg/**/*',
        'spec/**/*',
        'tmp/**/*',
        'vendor/**/*'
      ]
    )

    define_tasks
  end # namespace :puppet
end

Instance Attribute Details

#exclude_pathsObject (readonly)

Returns the value of attribute exclude_paths.



16
17
18
# File 'lib/vtasks/puppet.rb', line 16

def exclude_paths
  @exclude_paths
end

Instance Method Details

#check_puppetfileObject



111
112
113
114
# File 'lib/vtasks/puppet.rb', line 111

def check_puppetfile
  puppetfile.load
  error 'Puppetfile was not found or is empty!' if puppetfile.modules.empty?
end

#check_puppetfile_versionsObject

def generate_fixtures



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
# File 'lib/vtasks/puppet.rb', line 153

def check_puppetfile_versions
  puppetfile.load
  error 'Puppetfile was not found or is empty!' if puppetfile.modules.empty?

  puppetfile.modules.each do |mod|
    if mod.class == ::R10K::Module::Forge
      module_name = mod.title.tr('/', '-')
      forge_version = ::PuppetForge::Module.find(module_name)
                                           .current_release.version
      installed_version = mod.expected_version
      if installed_version != forge_version
        puts "#{module_name} is OUTDATED: " \
          "#{installed_version} vs #{forge_version} (#{::PuppetForge::Module.find(module_name).current_release.[:project_page]})"
          .red
      else
        puts "#{module_name}: #{forge_version}".green
      end
    elsif mod.class == ::R10K::Module::Git
      # Try to extract owner and repo name from remote string
      remote = mod.instance_variable_get('@remote')
      owner  = remote.gsub(%r{(.*)\/(.*)\/(.*)}, '\\2')
      repo   = remote.gsub(%r{(.*)\/(.*)\/}, '\\3')

      # It's better to query the API authenticated because of the rate
      # limit. You can make up to 5,000 requests per hour. For unauthenticated
      # requests, the rate limit is only up to 60 requests per hour.
      # (https://developer.github.com/v3/#rate-limiting)
      tags = if GITHUB_TOKEN
               open("https://api.github.com/repos/#{owner}/#{repo}/tags?access_token=#{GITHUB_TOKEN}")
             else
               open("https://api.github.com/repos/#{owner}/#{repo}/tags")
             end

      # Get rid of non-semantic versions (for example
      # https://github.com/puppetlabs/puppetlabs-ntp/releases/tag/push)
      all_tags = JSON.parse(tags.read).select do |tag|
        tag['name'] =~ /v?\d+\.\d+\.\d+/
      end

      # Use Gem::Version to sort tags
      latest_tag = all_tags.map do |line|
        ::Gem::Version.new line['name'].gsub(/[v]?(.*)/, '\\1')
      end.max.to_s

      # Print results
      installed_version = mod.version.gsub(/[v]?(.*)/, '\\1')
      if installed_version == 'master'
        puts "#{mod.title}: 'master' branch (#{latest_tag}) - #{remote}".blue
      elsif installed_version != latest_tag
        puts "#{mod.title} is OUTDATED: " \
          "#{installed_version} vs #{latest_tag} (#{remote})"
          .red
      else
        puts "#{mod.title}: #{latest_tag}".green
      end
    end
  end
end

#define_tasksObject



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
# File 'lib/vtasks/puppet.rb', line 53

def define_tasks
  ::PuppetLint::RakeTask.new :lint do |config|
    config.relative = true
    config.with_context = true
    config.fail_on_warnings = true
    config.ignore_paths = exclude_paths
    config.disable_checks = [
      '140chars'
    ]
  end

  # Puppet syntax tasks
  ::PuppetSyntax.exclude_paths = exclude_paths

  desc 'Run syntax, lint, and spec tests'
  task test: [
    :metadata_lint,
    :syntax,
    :lint,
    :unit
  ]

  desc 'Run unit tests'
  task unit: [
    :r10k_install_modules,
    :spec_prep,
    :spec_standalone
  ]

  desc 'Run acceptance tests'
  task integration: [
    :spec_prep,
    :beaker
  ]

  desc 'Clean all test files'
  task clean: [:spec_clean]

  desc 'Use R10K to download all modules'
  task :r10k_install_modules do
    r10k_install_modules
  end

  desc 'Generates a new .fixtures.yml from a Puppetfile'
  task :generate_fixtures do
    generate_fixtures
  end

  desc 'Print outdated Puppetfile modules'
  task :puppetfile_inspect do
    check_puppetfile_versions
  end
end

#generate_fixturesObject



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
# File 'lib/vtasks/puppet.rb', line 123

def generate_fixtures
  info 'Generating fixtures file'

  check_puppetfile

  fixtures = {
    'fixtures' => {
      'symlinks' => {
        'role' => '#{source_dir}/dist/role',
        'profile' => '#{source_dir}/dist/profile'
      },
      'repositories' => {}
    }
  }

  puppetfile.modules.each do |mod|
    module_name = mod.title.tr('/', '-')
    remote      = mod.instance_variable_get('@remote')
    ref         = mod.instance_variable_get('@desired_ref')

    fixtures['fixtures']['repositories'][module_name] = {
      'repo' => remote,
      'ref' => ref
    }
  end

  File.open('.fixtures.yml', 'w') { |file| file.write(fixtures.to_yaml) }
  info 'Done'
end

#puppetfileObject

def define_tasks



107
108
109
# File 'lib/vtasks/puppet.rb', line 107

def puppetfile
  @puppetfile ||= ::R10K::Puppetfile.new(pwd)
end

#r10k_install_modulesObject



116
117
118
119
120
121
# File 'lib/vtasks/puppet.rb', line 116

def r10k_install_modules
  info 'Updating modules with R10K'
  ::R10K::CLI.command.run(%w(puppetfile install --force --verbose))
rescue SystemExit # because R10K::CLI.command.run calls `exit 0`
  info 'Modules have been updated'
end