ra10ke 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +16 -0
- data/README.md +59 -1
- data/Rakefile +7 -1
- data/lib/ra10ke/dependencies.rb +71 -0
- data/lib/ra10ke/install.rb +32 -0
- data/lib/ra10ke/monkey_patches.rb +28 -0
- data/lib/ra10ke/puppetfile_parser.rb +83 -0
- data/lib/ra10ke/solve.rb +185 -189
- data/lib/ra10ke/syntax.rb +18 -0
- data/lib/ra10ke/validate.rb +126 -0
- data/lib/ra10ke/version.rb +1 -1
- data/lib/ra10ke.rb +29 -122
- data/ra10ke.gemspec +2 -0
- data/spec/fixtures/Puppetfile +43 -0
- data/spec/fixtures/Puppetfile_test +12 -0
- data/spec/fixtures/Puppetfile_with_bad_refs +10 -0
- data/spec/fixtures/reflist.txt +290 -0
- data/spec/ra10ke/puppetfile_parser_spec.rb +103 -0
- data/spec/ra10ke/validate_spec.rb +81 -0
- data/spec/ra10ke_spec.rb +73 -0
- data/spec/spec_helper.rb +3 -0
- metadata +45 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 244a7664e31597a415668faaeb3cf43b3c0243cf6aed478183f91317230e68eb
|
4
|
+
data.tar.gz: d241ae0aafcb1031dc1d6ef86a69796f79bcfefefe39622b22d5b165be34c696
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a889ad1d1f59c4781b895e7abc1f05b0b24776f7976f6c01bb6e45f258239908413f39d5e95def2cc032475243cb27aa39087b937fe6dd3e0a35147b28a6c0bb
|
7
|
+
data.tar.gz: e4ee4b06d70659f4fc836b90eb73ce22b1fc28076076704da334db5e52ddcd5fe138a0cf95edf80a86afea4885d1fd7fe883621ee04c0fc975a3ac32047711f9
|
data/.gitignore
CHANGED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.5.3
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,22 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
=========
|
3
3
|
|
4
|
+
0.6.0
|
5
|
+
-----
|
6
|
+
|
7
|
+
2019-07-30
|
8
|
+
|
9
|
+
Closed Pull Requests:
|
10
|
+
|
11
|
+
* [#35](https://github.com/voxpupuli/ra10ke/pull/35) Adds new validate task for verifying the integrity of all modules specified in the Puppetfile
|
12
|
+
* [#33](https://github.com/voxpupuli/ra10ke/pull/33) Refactor tasks, Version tag handling fix, purge option
|
13
|
+
* [#32](https://github.com/voxpupuli/ra10ke/pull/32) Make it possible to configure the tasks in the rakefile
|
14
|
+
|
15
|
+
Many thanks to the following contributors for submitting PRs:
|
16
|
+
|
17
|
+
* [Corey Osman](https://github.com/logicminds)
|
18
|
+
* [Andreas Zuber](https://github.com/ZeroPointEnergy)
|
19
|
+
|
4
20
|
0.5.0
|
5
21
|
-----
|
6
22
|
|
data/README.md
CHANGED
@@ -13,12 +13,35 @@ Add the following line to your `Gemfile`:
|
|
13
13
|
gem 'ra10ke'
|
14
14
|
```
|
15
15
|
|
16
|
-
Add the following
|
16
|
+
Add the following lines in your `Rakefile`:
|
17
17
|
|
18
18
|
```ruby
|
19
19
|
require 'ra10ke'
|
20
|
+
Ra10ke::RakeTask.new
|
20
21
|
```
|
21
22
|
|
23
|
+
## Configuration
|
24
|
+
|
25
|
+
You can configure the tasks in a block:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
Ra10ke::RakeTask.new do |t|
|
29
|
+
t.basedir = File.join(Dir.pwd, 'some_dir')
|
30
|
+
t.moduledir = File.join(Dir.pwd, 'some_dir/strange_module_dir')
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
Available settings are:
|
35
|
+
|
36
|
+
| Setting | Documentation |
|
37
|
+
|-----------------|-----------------------------------------------------------------------------------------------|
|
38
|
+
| basedir | Base directory with the Puppetfile and modules directory (Default: Same directory as Rakefile)|
|
39
|
+
| moduledir | Directory to install the modules in (Default: 'modules' in basedir) |
|
40
|
+
| puppetfile_path | Directroy where the Puppetfile is (Default: basedir) |
|
41
|
+
| puppetfile_name | The Puppetfile name (Default: basedir/Puppetfile) |
|
42
|
+
| force | Overwrite locally changed files on install (Default: false) |
|
43
|
+
| purge | Purge unmanaged modules from the modulesdir (Default: false) |
|
44
|
+
|
22
45
|
## Rake tasks
|
23
46
|
|
24
47
|
### r10k:syntax
|
@@ -56,6 +79,41 @@ runs faster.
|
|
56
79
|
|
57
80
|
Reads the Puppetfile in the current directory and installs them under the `path` provided as an argument.
|
58
81
|
|
82
|
+
### r10k:validate[path]
|
83
|
+
The validate rake task will determine if the url is a valid url by connecting
|
84
|
+
to the repository and verififying it actually exists and can be accessed.
|
85
|
+
Additional if a branch, tag, or ref is specified in the Puppetfile the validate
|
86
|
+
task will also verify that that branch/tag/ref exists in the remote repository.
|
87
|
+
|
88
|
+
If you have ever deployed r10k to production only to find out a tag or branch is
|
89
|
+
missing this validate task will catch that issue.
|
90
|
+
|
91
|
+
A exit status of 0 is returned if there are no faults, while a 1 is returned if
|
92
|
+
any module has a bad status.
|
93
|
+
|
94
|
+
Status emojis can be customized by setting the following environment variables.
|
95
|
+
|
96
|
+
Example
|
97
|
+
|
98
|
+
* `GOOD_EMOJI='👍'`
|
99
|
+
* `BAD_EMOJI='😨'`
|
100
|
+
|
101
|
+
|
102
|
+
```
|
103
|
+
NAME | URL | REF | STATUS
|
104
|
+
---------|-----------------------------------------------|--------------------------------|-------
|
105
|
+
splunk | https://github.com/cudgel/splunk.git | prod | 👍
|
106
|
+
r10k | https://github.com/acidprime/r10k | v3.1.1 | 👍
|
107
|
+
gms | https://github.com/npwalker/abrader-gms | gitlab_disable_ssl_verify_s... | 👍
|
108
|
+
rbac | https://github.com/puppetlabs/pltraining-rbac | 2f60e1789a721ce83f8df061e13... | 👍
|
109
|
+
acl | https://github.com/dobbymoodge/puppet-acl.git | master | 👍
|
110
|
+
deploy | https://github.com/cudgel/deploy.git | master | 👍
|
111
|
+
dotfiles | https://github.com/cudgel/puppet-dotfiles.git | master | 👍
|
112
|
+
gitlab | https://github.com/vshn/puppet-gitlab | 00397b86dfb3487d9df768cbd36... | 👍
|
113
|
+
|
114
|
+
👍👍 Puppetfile looks good.👍👍
|
115
|
+
```
|
116
|
+
|
59
117
|
#### Limitations
|
60
118
|
|
61
119
|
* It works only with modules from the [Forge](https://forge.puppetlabs.com), and Git.
|
data/Rakefile
CHANGED
@@ -3,8 +3,14 @@ require 'rake/clean'
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'bundler/gem_tasks'
|
5
5
|
require 'fileutils'
|
6
|
+
require 'rspec/core'
|
7
|
+
require 'rspec/core/rake_task'
|
6
8
|
|
7
9
|
CLEAN.include("pkg/", "tmp/")
|
8
10
|
CLOBBER.include("Gemfile.lock")
|
9
11
|
|
10
|
-
task :default => [:
|
12
|
+
task :default => [:spec]
|
13
|
+
|
14
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
15
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
16
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Ra10ke::Dependencies
|
2
|
+
def define_task_dependencies(*_args)
|
3
|
+
desc "Print outdated forge modules"
|
4
|
+
task :dependencies do
|
5
|
+
require 'r10k/puppetfile'
|
6
|
+
require 'puppet_forge'
|
7
|
+
|
8
|
+
PuppetForge.user_agent = "ra10ke/#{Ra10ke::VERSION}"
|
9
|
+
puppetfile = get_puppetfile
|
10
|
+
puppetfile.load!
|
11
|
+
PuppetForge.host = puppetfile.forge if puppetfile.forge =~ /^http/
|
12
|
+
|
13
|
+
# ignore file allows for "don't tell me about this"
|
14
|
+
ignore_modules = []
|
15
|
+
if File.exist?('.r10kignore')
|
16
|
+
ignore_modules = File.readlines('.r10kignore').each {|l| l.chomp!}
|
17
|
+
end
|
18
|
+
|
19
|
+
puppetfile.modules.each do |puppet_module|
|
20
|
+
next if ignore_modules.include? puppet_module.title
|
21
|
+
if puppet_module.class == R10K::Module::Forge
|
22
|
+
module_name = puppet_module.title.gsub('/', '-')
|
23
|
+
forge_version = PuppetForge::Module.find(module_name).current_release.version
|
24
|
+
installed_version = puppet_module.expected_version
|
25
|
+
if installed_version != forge_version
|
26
|
+
puts "#{puppet_module.title} is OUTDATED: #{installed_version} vs #{forge_version}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
if puppet_module.class == R10K::Module::Git
|
31
|
+
# use helper; avoid `desired_ref`
|
32
|
+
# we do not want to deal with `:control_branch`
|
33
|
+
ref = puppet_module.version
|
34
|
+
next unless ref
|
35
|
+
|
36
|
+
remote = puppet_module.instance_variable_get(:@remote)
|
37
|
+
remote_refs = Git.ls_remote(remote)
|
38
|
+
|
39
|
+
# skip if ref is a branch
|
40
|
+
next if remote_refs['branches'].key?(ref)
|
41
|
+
|
42
|
+
if remote_refs['tags'].key?(ref)
|
43
|
+
# there are too many possible versioning conventions
|
44
|
+
# we have to be be opinionated here
|
45
|
+
# so semantic versioning (vX.Y.Z) it is for us
|
46
|
+
# as well as support for skipping the leading v letter
|
47
|
+
tags = remote_refs['tags'].keys
|
48
|
+
latest_tag = tags.map do |tag|
|
49
|
+
begin
|
50
|
+
Semverse::Version.new tag[/\Av?(.*)\Z/, 1]
|
51
|
+
rescue Semverse::InvalidVersionFormat
|
52
|
+
# ignore tags that do not comply to semver
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
end.select { |tag| !tag.nil? }.sort.last.to_s.downcase
|
56
|
+
latest_ref = tags.detect { |tag| tag[/\Av?(.*)\Z/, 1] == latest_tag }
|
57
|
+
latest_ref = 'undef (tags do not match semantic versioning)' if latest_ref.nil?
|
58
|
+
elsif ref.match(/^[a-z0-9]{40}$/)
|
59
|
+
# for sha just assume head should be tracked
|
60
|
+
latest_ref = remote_refs['head'][:sha]
|
61
|
+
else
|
62
|
+
raise "Unable to determine ref type for #{puppet_module.title}"
|
63
|
+
end
|
64
|
+
|
65
|
+
puts "#{puppet_module.title} is OUTDATED: #{ref} vs #{latest_ref}" if ref != latest_ref
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Ra10ke::Install
|
2
|
+
def define_task_install(*_args)
|
3
|
+
desc "Install modules specified in Puppetfile"
|
4
|
+
task :install do
|
5
|
+
require 'r10k/puppetfile'
|
6
|
+
|
7
|
+
puppetfile = get_puppetfile
|
8
|
+
puppetfile.load!
|
9
|
+
|
10
|
+
puts "Processing Puppetfile for fixtures"
|
11
|
+
puppetfile.modules.each do |mod|
|
12
|
+
if mod.status == :insync
|
13
|
+
puts "Skipping #{mod.name} (#{mod.version}) already in sync"
|
14
|
+
else
|
15
|
+
if mod.status == :absent
|
16
|
+
msg = "installed #{mod.name}"
|
17
|
+
else
|
18
|
+
msg = "updated #{mod.name} from #{mod.version} to"
|
19
|
+
end
|
20
|
+
mod.sync
|
21
|
+
if mod.status != :insync
|
22
|
+
puts "Failed to sync #{mod.name}".red
|
23
|
+
else
|
24
|
+
puts "Successfully #{msg} #{mod.version}".green
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
puppetfile.purge! if @purge
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class String
|
4
|
+
# colorization
|
5
|
+
def colorize(color_code)
|
6
|
+
"\e[#{color_code}m#{self}\e[0m"
|
7
|
+
end
|
8
|
+
|
9
|
+
def red
|
10
|
+
colorize(31)
|
11
|
+
end
|
12
|
+
|
13
|
+
def green
|
14
|
+
colorize(32)
|
15
|
+
end
|
16
|
+
|
17
|
+
def yellow
|
18
|
+
colorize(33)
|
19
|
+
end
|
20
|
+
|
21
|
+
# removes specified markes from string.
|
22
|
+
# @return [String] - the string with markers removed
|
23
|
+
def strip_comment(markers = ['#', "\n"])
|
24
|
+
re = Regexp.union(markers)
|
25
|
+
index = (self =~ re)
|
26
|
+
index.nil? ? rstrip : self[0, index].rstrip
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# it might be desirable to parse the Puppetfile as a string instead of evaling it.
|
2
|
+
# this module allows you to do just that.
|
3
|
+
require 'ra10ke/monkey_patches'
|
4
|
+
|
5
|
+
module Ra10ke
|
6
|
+
module PuppetfileParser
|
7
|
+
|
8
|
+
# @return [Array] - returns a array of hashes that contain modules with a git source
|
9
|
+
def git_modules(file = puppetfile)
|
10
|
+
modules(file).find_all do |mod|
|
11
|
+
mod[:args].key?(:git)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param puppetfile [String] - the absolute path to the puppetfile
|
16
|
+
# @return [Array] - returns an array of module hashes that represent the puppetfile
|
17
|
+
# @example
|
18
|
+
# [{:namespace=>"puppetlabs", :name=>"stdlib", :args=>[]},
|
19
|
+
# {:namespace=>"petems", :name=>"swap_file", :args=>["'4.0.0'"]}]
|
20
|
+
def modules(puppetfile)
|
21
|
+
@modules ||= begin
|
22
|
+
return [] unless File.exist?(puppetfile)
|
23
|
+
|
24
|
+
all_lines = File.read(puppetfile).lines.map(&:strip_comment)
|
25
|
+
# remove comments from all the lines
|
26
|
+
lines_without_comments = all_lines.reject { |line| line.match(/#.*\n/) }.join("\n").delete("\n")
|
27
|
+
lines_without_comments.split('mod').map do |line|
|
28
|
+
next nil if line =~ /^forge/
|
29
|
+
next nil if line.empty?
|
30
|
+
|
31
|
+
parse_module_args(line)
|
32
|
+
end.compact.uniq
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# @param data [String] - the string to parse the puppetfile args out of
|
37
|
+
# @return [Array] - an array of arguments in hash form
|
38
|
+
# @example
|
39
|
+
# {:namespace=>"puppetlabs", :name=>"stdlib", :args=>[]}
|
40
|
+
# {:namespace=>"petems", :name=>"swap_file", :args=>["'4.0.0'"]}
|
41
|
+
def parse_module_args(data)
|
42
|
+
return {} if data.empty?
|
43
|
+
args = data.split(',').map(&:strip)
|
44
|
+
# we can't guarantee that there will be a namespace when git is used
|
45
|
+
# remove quotes and dash and slash
|
46
|
+
namespace, name = args.shift.gsub(/'|"/, '').split(%r{-|/})
|
47
|
+
name ||= namespace
|
48
|
+
namespace = nil if namespace == name
|
49
|
+
{
|
50
|
+
namespace: namespace,
|
51
|
+
name: name,
|
52
|
+
args: process_args(args)
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [Array] - returns an array of hashes with the args in key value pairs
|
57
|
+
# @param [Array] - the arguments processed from each entry in the puppetfile
|
58
|
+
# @example
|
59
|
+
# [{:args=>[], :name=>"razor", :namespace=>"puppetlabs"},
|
60
|
+
# {:args=>[{:version=>"0.0.3"}], :name=>"ntp", :namespace=>"puppetlabs"},
|
61
|
+
# {:args=>[], :name=>"inifile", :namespace=>"puppetlabs"},
|
62
|
+
# {:args=>
|
63
|
+
# [{:git=>"https://github.com/nwops/reportslack.git"}, {:ref=>"1.0.20"}],
|
64
|
+
# :name=>"reportslack",
|
65
|
+
# :namespace=>"nwops"},
|
66
|
+
# {:args=>{:git=>"git://github.com/puppetlabs/puppetlabs-apt.git"},
|
67
|
+
# :name=>"apt",
|
68
|
+
# :namespace=>nil}
|
69
|
+
# ]
|
70
|
+
def process_args(args)
|
71
|
+
results = {}
|
72
|
+
args.each do |arg|
|
73
|
+
a = arg.gsub(/'|"/, '').split(/\A\:|\:\s|\=\>/).map(&:strip).reject(&:empty?)
|
74
|
+
if a.count < 2
|
75
|
+
results[:version] = a.first
|
76
|
+
else
|
77
|
+
results[a.first.to_sym] = a.last
|
78
|
+
end
|
79
|
+
end
|
80
|
+
results
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|