ra10ke 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|