helmsnap 0.1.0 → 0.3.2
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/.dockerignore +8 -0
- data/.rubocop.yml +16 -12
- data/Dockerfile +12 -0
- data/Gemfile.lock +44 -5
- data/README.md +47 -16
- data/bin/setup +8 -0
- data/exe/helmsnap +2 -113
- data/helmsnap.gemspec +6 -2
- data/lib/helmsnap/args_parser.rb +68 -0
- data/lib/helmsnap/check.rb +35 -0
- data/lib/helmsnap/command.rb +48 -0
- data/lib/helmsnap/console.rb +19 -0
- data/lib/helmsnap/generate.rb +47 -0
- data/lib/helmsnap/runner.rb +67 -0
- data/lib/helmsnap/version.rb +1 -1
- data/lib/helmsnap.rb +22 -1
- metadata +42 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b55e83c50e04e5cba9d2a16b4e805a1427f0de01fb7e00fcbf00aab0a105b4a8
|
4
|
+
data.tar.gz: 443d1fb5af1df2471a9d521c216c0199a7f005a10c94ae0c14b71d01bedf6de7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78819d406edbdda47378143189c28b2f83c227f3f5ed1e0d8834bb81441a81200bb6f77b0413cd5903b0e25960515717016d67bc1021bc0e66eca5912cde543b
|
7
|
+
data.tar.gz: d599a6a266c749ca60c50a05b383a425e198b67200993eb97009ccac91ab75c67952f2795f3b11f0de56dcfe7916e5f6f10217ebaea18311675563489ffc0026
|
data/.dockerignore
ADDED
data/.rubocop.yml
CHANGED
@@ -1,13 +1,17 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
Style/StringLiterals:
|
5
|
-
Enabled: true
|
6
|
-
EnforcedStyle: double_quotes
|
1
|
+
inherit_gem:
|
2
|
+
rubocop-config-umbrellio: lib/rubocop.yml
|
7
3
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
4
|
+
AllCops:
|
5
|
+
DisplayCopNames: true
|
6
|
+
TargetRubyVersion: 2.7
|
7
|
+
Include:
|
8
|
+
- bin/console
|
9
|
+
- Gemfile
|
10
|
+
- helmsnap.gemspec
|
11
|
+
- Rakefile
|
12
|
+
- lib/**/*
|
13
|
+
- spec/**/*
|
14
|
+
- gemfile/**/*
|
15
|
+
Exclude:
|
16
|
+
- vendor/**/*
|
17
|
+
- gemfiles/**/*
|
data/Dockerfile
ADDED
data/Gemfile.lock
CHANGED
@@ -1,21 +1,34 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
helmsnap (0.
|
4
|
+
helmsnap (0.3.2)
|
5
|
+
colorize
|
5
6
|
|
6
7
|
GEM
|
7
8
|
remote: https://rubygems.org/
|
8
9
|
specs:
|
10
|
+
activesupport (6.1.4.1)
|
11
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
|
+
i18n (>= 1.6, < 2)
|
13
|
+
minitest (>= 5.1)
|
14
|
+
tzinfo (~> 2.0)
|
15
|
+
zeitwerk (~> 2.3)
|
9
16
|
ast (2.4.2)
|
10
17
|
coderay (1.1.3)
|
18
|
+
colorize (0.8.1)
|
19
|
+
concurrent-ruby (1.1.9)
|
11
20
|
diff-lcs (1.4.4)
|
21
|
+
i18n (1.8.11)
|
22
|
+
concurrent-ruby (~> 1.0)
|
12
23
|
method_source (1.0.0)
|
24
|
+
minitest (5.14.4)
|
13
25
|
parallel (1.21.0)
|
14
|
-
parser (3.0.
|
26
|
+
parser (3.0.3.0)
|
15
27
|
ast (~> 2.4.1)
|
16
28
|
pry (0.14.1)
|
17
29
|
coderay (~> 1.1)
|
18
30
|
method_source (~> 1.0)
|
31
|
+
rack (2.2.3)
|
19
32
|
rainbow (3.0.0)
|
20
33
|
rake (13.0.6)
|
21
34
|
regexp_parser (2.1.1)
|
@@ -33,22 +46,47 @@ GEM
|
|
33
46
|
diff-lcs (>= 1.2.0, < 2.0)
|
34
47
|
rspec-support (~> 3.10.0)
|
35
48
|
rspec-support (3.10.3)
|
36
|
-
rubocop (1.
|
49
|
+
rubocop (1.17.0)
|
37
50
|
parallel (~> 1.10)
|
38
51
|
parser (>= 3.0.0.0)
|
39
52
|
rainbow (>= 2.2.2, < 4.0)
|
40
53
|
regexp_parser (>= 1.8, < 3.0)
|
41
54
|
rexml
|
42
|
-
rubocop-ast (>= 1.
|
55
|
+
rubocop-ast (>= 1.7.0, < 2.0)
|
43
56
|
ruby-progressbar (~> 1.7)
|
44
57
|
unicode-display_width (>= 1.4.0, < 3.0)
|
45
58
|
rubocop-ast (1.13.0)
|
46
59
|
parser (>= 3.0.1.1)
|
60
|
+
rubocop-config-umbrellio (1.17.0.53)
|
61
|
+
rubocop (= 1.17.0)
|
62
|
+
rubocop-performance (= 1.10.0)
|
63
|
+
rubocop-rails (= 2.9.1)
|
64
|
+
rubocop-rake (= 0.5.1)
|
65
|
+
rubocop-rspec (= 2.2.0)
|
66
|
+
rubocop-sequel (= 0.2.0)
|
67
|
+
rubocop-performance (1.10.0)
|
68
|
+
rubocop (>= 0.90.0, < 2.0)
|
69
|
+
rubocop-ast (>= 0.4.0)
|
70
|
+
rubocop-rails (2.9.1)
|
71
|
+
activesupport (>= 4.2.0)
|
72
|
+
rack (>= 1.1)
|
73
|
+
rubocop (>= 0.90.0, < 2.0)
|
74
|
+
rubocop-rake (0.5.1)
|
75
|
+
rubocop
|
76
|
+
rubocop-rspec (2.2.0)
|
77
|
+
rubocop (~> 1.0)
|
78
|
+
rubocop-ast (>= 1.1.0)
|
79
|
+
rubocop-sequel (0.2.0)
|
80
|
+
rubocop (~> 1.0)
|
47
81
|
ruby-progressbar (1.11.0)
|
82
|
+
tzinfo (2.0.4)
|
83
|
+
concurrent-ruby (~> 1.0)
|
48
84
|
unicode-display_width (2.1.0)
|
85
|
+
zeitwerk (2.5.1)
|
49
86
|
|
50
87
|
PLATFORMS
|
51
88
|
x86_64-darwin-20
|
89
|
+
x86_64-linux
|
52
90
|
|
53
91
|
DEPENDENCIES
|
54
92
|
helmsnap!
|
@@ -56,6 +94,7 @@ DEPENDENCIES
|
|
56
94
|
rake
|
57
95
|
rspec
|
58
96
|
rubocop
|
97
|
+
rubocop-config-umbrellio
|
59
98
|
|
60
99
|
BUNDLED WITH
|
61
|
-
2.2.
|
100
|
+
2.2.32
|
data/README.md
CHANGED
@@ -1,38 +1,69 @@
|
|
1
1
|
# Helmsnap
|
2
2
|
|
3
|
-
|
3
|
+
## About
|
4
4
|
|
5
|
-
|
5
|
+
Helmsnap is a tool for generating and checking helm chart snapshots. Example:
|
6
6
|
|
7
|
-
|
7
|
+
Generate snapshots (uses `helm template` under the hood):
|
8
|
+
|
9
|
+
```sh
|
10
|
+
helmsnap generate -c helm/mychart -s helm/snapshots -v helm/values/production.yaml
|
11
|
+
```
|
12
|
+
|
13
|
+
Generate snapshots in some temp directory and check (diff) them against existing snapshots in `helm/snapshots` directory:
|
8
14
|
|
9
|
-
|
15
|
+
```sh
|
16
|
+
helmsnap check -c helm/mychart -s helm/snapshots -v helm/values/production.yaml
|
17
|
+
```
|
18
|
+
|
19
|
+
Get the full description of possible arguments:
|
10
20
|
|
11
|
-
```
|
12
|
-
|
21
|
+
```sh
|
22
|
+
helmsnap --help
|
13
23
|
```
|
14
24
|
|
15
|
-
|
25
|
+
The typical usage flow:
|
16
26
|
|
17
|
-
|
27
|
+
1. You generate some snapshots using `helmsnap generate` command and check them into your git repo.
|
28
|
+
2. You add `helmsnap check` command to your CI (or run it manually on every commit).
|
29
|
+
3. In case snapshots differ, you should carefully check the updates and either fix your chart or update the snapshots using `helmsnap generate`.
|
18
30
|
|
19
|
-
|
31
|
+
This tool can also be useful when you are developing a new chart or updating an existing one: you can generate snapshots and see what is rendered without need to deploy the chart in your cluster.
|
20
32
|
|
21
|
-
|
33
|
+
## Features
|
22
34
|
|
23
|
-
|
35
|
+
### Helm dependency management
|
24
36
|
|
25
|
-
|
37
|
+
Helmsnap will automically rebuild your chart dependencies on every snapshot generation or check. In case your dependency is using url to some local helm repo and you don't have a proper repo added, it will add it automically which is useful in CI. It also will detect local dependencies (those that start with `file://`) and rebuild their dependencies as well.
|
26
38
|
|
27
|
-
|
39
|
+
### Timestamp replacement
|
28
40
|
|
29
|
-
|
41
|
+
Helmsnap will automically replace all occurencies of patterns that look like timestamps (format like `2022-01-01 00:00:00.000`) in your templates. This is useful in case you have some annotations like `releaseTime` that would break your snapshots checks otherwise.
|
42
|
+
|
43
|
+
## Installation
|
30
44
|
|
31
|
-
|
45
|
+
Just install a gem and use the provided `helmsnap` binary.
|
46
|
+
|
47
|
+
```sh
|
48
|
+
gem install helmsnap
|
49
|
+
```
|
50
|
+
|
51
|
+
Alaternatively, you can use a [Docker image](https://github.com/tycooon/helmsnap/pkgs/container/helmsnap) with Ruby, helm and helmsnap gem preinstalled. This is useful for CIs or if you don't want to install Ruby locally.
|
52
|
+
|
53
|
+
## CI example
|
54
|
+
|
55
|
+
Example job for Gitlab CI:
|
56
|
+
|
57
|
+
```yaml
|
58
|
+
check-snapshots:
|
59
|
+
stage: test
|
60
|
+
image: ghcr.io/tycooon/helmsnap:latest
|
61
|
+
script: helmsnap check -c helm/mychart -s helm/snapshots -v helm/values/production.yaml
|
62
|
+
```
|
32
63
|
|
33
64
|
## Contributing
|
34
65
|
|
35
|
-
Bug reports and pull requests are welcome
|
66
|
+
Bug reports and pull requests are welcome.
|
36
67
|
|
37
68
|
## License
|
38
69
|
|
data/bin/setup
ADDED
data/exe/helmsnap
CHANGED
@@ -1,117 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
require "fileutils"
|
6
|
-
require "open3"
|
7
|
-
require "optparse"
|
8
|
-
require "pathname"
|
9
|
-
require "shellwords"
|
4
|
+
require_relative "../lib/helmsnap"
|
10
5
|
|
11
|
-
|
12
|
-
cmd = Shellwords.join(cmd_parts)
|
13
|
-
|
14
|
-
puts "\e[1m\e[33m#{cmd}\e[0m\e[22m"
|
15
|
-
|
16
|
-
Open3.popen3(cmd) do |_stdin, stdout, stderr, wait_thr|
|
17
|
-
output = +""
|
18
|
-
|
19
|
-
while chunk = stdout.gets
|
20
|
-
$stdout.print(chunk)
|
21
|
-
output << chunk
|
22
|
-
end
|
23
|
-
|
24
|
-
exit_status = wait_thr.value
|
25
|
-
|
26
|
-
unless exit_status.success?
|
27
|
-
$stderr.print(stderr.read)
|
28
|
-
abort "Command failed with status #{exit_status.to_i}"
|
29
|
-
end
|
30
|
-
|
31
|
-
puts
|
32
|
-
output
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
class ArgsParser
|
37
|
-
Args = Struct.new(:chart, :snapshots, :values)
|
38
|
-
MissingOption = Class.new(OptionParser::ParseError)
|
39
|
-
|
40
|
-
def initialize(options)
|
41
|
-
self.options = options
|
42
|
-
self.args = Args.new("k8s/chart", "k8s/snapshots")
|
43
|
-
self.parser = build_parser
|
44
|
-
end
|
45
|
-
|
46
|
-
def get_options!
|
47
|
-
parser.parse!(options)
|
48
|
-
raise MissingOption, "missing option: VALUES" unless args.values
|
49
|
-
args
|
50
|
-
rescue OptionParser::ParseError => e
|
51
|
-
puts e, nil
|
52
|
-
print_help!
|
53
|
-
exit 1
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
attr_accessor :options, :parser, :args
|
59
|
-
|
60
|
-
def build_parser
|
61
|
-
OptionParser.new do |opts|
|
62
|
-
opts.banner = "Usage: render-helm [options]"
|
63
|
-
|
64
|
-
opts.on("-c", "--chart-dir [DIR]",
|
65
|
-
"Chart directory (default: #{args.chart})") do |option|
|
66
|
-
args.chart = option
|
67
|
-
end
|
68
|
-
|
69
|
-
opts.on("-s", "--snapshots-dir DIR",
|
70
|
-
"Snapshots directory (default #{args.snapshots})") do |option|
|
71
|
-
args.snapshots = option
|
72
|
-
end
|
73
|
-
|
74
|
-
opts.on("-v", "--values VALUES", "Values file") do |option|
|
75
|
-
args.values = option
|
76
|
-
end
|
77
|
-
|
78
|
-
opts.on("-h", "--help", "Show this message") do
|
79
|
-
puts opts
|
80
|
-
exit
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def print_help!
|
86
|
-
puts parser.help
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
options = ArgsParser.new(ARGV).get_options!
|
91
|
-
|
92
|
-
chart_path = Pathname.new(options.chart)
|
93
|
-
snapshots_path = Pathname.new(options.snapshots)
|
94
|
-
|
95
|
-
dep_list = run "helm", "dependency", "list", "--max-col-width", 0, chart_path
|
96
|
-
|
97
|
-
dep_list.scan(%r{file://(.+?)\t}) do |dep_path|
|
98
|
-
run "helm", "dependency", "update", "--skip-refresh", chart_path.join(dep_path.first)
|
99
|
-
end
|
100
|
-
|
101
|
-
dep_list.scan(%r{(https?://.+?)\t}) do |dep_path|
|
102
|
-
run "helm", "repo", "add", Digest::MD5.hexdigest(dep_path.first), dep_path.first
|
103
|
-
end
|
104
|
-
|
105
|
-
run "helm", "dependency", "update", "--skip-refresh", chart_path
|
106
|
-
|
107
|
-
FileUtils.rmtree(snapshots_path)
|
108
|
-
|
109
|
-
run "helm", "template", chart_path,
|
110
|
-
"--values", options.values,
|
111
|
-
"--output-dir", snapshots_path
|
112
|
-
|
113
|
-
snapshots_path.glob(["**/*yaml", "**/*.yml"]).each do |path|
|
114
|
-
content = path.read
|
115
|
-
content.gsub!(/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d+/, "2022-01-01 00:00:00.000") or next
|
116
|
-
path.write(content)
|
117
|
-
end
|
6
|
+
Helmsnap::Runner.call(ARGV)
|
data/helmsnap.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.summary = "A tool for creating and checking helm chart snapshots."
|
12
12
|
spec.homepage = "https://github.com/tycooon/helmsnap"
|
13
13
|
spec.license = "MIT"
|
14
|
-
spec.required_ruby_version = ">= 2.
|
14
|
+
spec.required_ruby_version = ">= 2.7.0"
|
15
15
|
|
16
16
|
# spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
|
17
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
@@ -22,11 +22,15 @@ Gem::Specification.new do |spec|
|
|
22
22
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
23
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
24
24
|
`git ls-files -z`.split("\x0").reject do |f|
|
25
|
-
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)
|
25
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci))})
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
29
|
spec.bindir = "exe"
|
30
30
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
31
31
|
spec.require_paths = ["lib"]
|
32
|
+
|
33
|
+
spec.add_dependency "colorize"
|
34
|
+
|
35
|
+
spec.add_development_dependency "rubocop-config-umbrellio"
|
32
36
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Helmsnap::ArgsParser
|
4
|
+
Args = Struct.new(:chart_path, :snapshots_path, :values_path, keyword_init: true)
|
5
|
+
MissingOption = Class.new(OptionParser::ParseError)
|
6
|
+
|
7
|
+
BANNER = "Usage: helmsnap CMD [options]"
|
8
|
+
|
9
|
+
def initialize(options)
|
10
|
+
self.options = options
|
11
|
+
self.args = Args.new
|
12
|
+
self.parser = build_parser
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_options!
|
16
|
+
parser.parse!(options)
|
17
|
+
raise MissingOption, "Missing option: CHARTDIR" unless args.chart_path
|
18
|
+
raise MissingOption, "Missing option: SNAPDIR" unless args.snapshots_path
|
19
|
+
raise MissingOption, "Missing option: VALUES" unless args.values_path
|
20
|
+
args
|
21
|
+
rescue OptionParser::ParseError => error
|
22
|
+
print_help!(error)
|
23
|
+
end
|
24
|
+
|
25
|
+
def print_help!(msg)
|
26
|
+
Helmsnap::Console.error($stderr, "#{msg}\n") if msg
|
27
|
+
Helmsnap::Console.print($stdout, parser.help)
|
28
|
+
exit 1
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_accessor :options, :parser, :args
|
34
|
+
|
35
|
+
def build_parser # rubocop:disable Metrics/MethodLength
|
36
|
+
OptionParser.new(BANNER, 50) do |opts|
|
37
|
+
opts.separator("Supported commands: `generate` and `check`.")
|
38
|
+
opts.separator("")
|
39
|
+
opts.separator("Specific options:")
|
40
|
+
|
41
|
+
opts.on("-c", "--chart-dir CHARTDIR", "Chart directory") do |option|
|
42
|
+
args.chart_path = pn(option)
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on("-s", "--snapshots-dir SNAPDIR", "Snapshots directory") do |option|
|
46
|
+
args.snapshots_path = pn(option)
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on("-v", "--values VALUES", "Values file") do |option|
|
50
|
+
args.values_path = pn(option)
|
51
|
+
end
|
52
|
+
|
53
|
+
opts.on("--version", "Show version") do
|
54
|
+
Helmsnap::Console.print($stdout, "#{Helmsnap::VERSION}\n")
|
55
|
+
exit
|
56
|
+
end
|
57
|
+
|
58
|
+
opts.on("-h", "--help", "Show this message") do
|
59
|
+
print_help!(nil)
|
60
|
+
exit
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def pn(...)
|
66
|
+
Pathname.new(...)
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Helmsnap::Check
|
4
|
+
def self.call(...)
|
5
|
+
new(...).call
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(chart_path:, snapshots_path:, values_path:)
|
9
|
+
self.chart_path = chart_path
|
10
|
+
self.snapshots_path = snapshots_path
|
11
|
+
self.values_path = values_path
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
Dir.mktmpdir do |temp_dir|
|
16
|
+
temp_dir_path = Pathname.new(temp_dir)
|
17
|
+
|
18
|
+
Helmsnap::Generate.call(
|
19
|
+
chart_path: chart_path,
|
20
|
+
snapshots_path: temp_dir_path,
|
21
|
+
values_path: values_path,
|
22
|
+
)
|
23
|
+
|
24
|
+
result = Helmsnap.run_cmd("which", "colordiff", allow_failure: true)
|
25
|
+
util = result.success ? "colordiff" : "diff"
|
26
|
+
|
27
|
+
diff = Helmsnap.run_cmd(util, "-r", temp_dir_path, snapshots_path, allow_failure: true).output
|
28
|
+
diff.strip.empty?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
attr_accessor :chart_path, :snapshots_path, :values_path
|
35
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Helmsnap::Command
|
4
|
+
Result = Struct.new(:success, :output)
|
5
|
+
|
6
|
+
def self.call(...)
|
7
|
+
new(...).call
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(cmd, stdout: $stdout, stderr: $stderr, allow_failure: false)
|
11
|
+
self.cmd = cmd
|
12
|
+
self.stdout = stdout
|
13
|
+
self.stderr = stderr
|
14
|
+
self.allow_failure = allow_failure
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
Helmsnap::Console.info(stdout, "> #{cmd}")
|
19
|
+
run_command
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_accessor :cmd, :stdout, :stderr, :allow_failure
|
25
|
+
|
26
|
+
def run_command
|
27
|
+
Open3.popen3(cmd) do |_in, out, err, wait_thr|
|
28
|
+
output = +""
|
29
|
+
|
30
|
+
while (chunk = out.gets)
|
31
|
+
Helmsnap::Console.print(stdout, chunk)
|
32
|
+
output << chunk
|
33
|
+
end
|
34
|
+
|
35
|
+
exit_status = wait_thr.value
|
36
|
+
success = exit_status.success?
|
37
|
+
|
38
|
+
if !success && !allow_failure
|
39
|
+
Helmsnap::Console.error(stderr, err.read)
|
40
|
+
Helmsnap::Console.error(stderr, "Command failed with status #{exit_status.to_i}")
|
41
|
+
abort
|
42
|
+
end
|
43
|
+
|
44
|
+
Helmsnap::Console.print(stdout, "\n")
|
45
|
+
Result.new(success, output)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Helmsnap::Console
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def print(stream, msg)
|
7
|
+
stream.print(msg)
|
8
|
+
end
|
9
|
+
|
10
|
+
def info(stream, msg)
|
11
|
+
msg = ColorizedString[msg].colorize(:light_yellow)
|
12
|
+
stream.puts(msg)
|
13
|
+
end
|
14
|
+
|
15
|
+
def error(stream, msg)
|
16
|
+
msg = ColorizedString[msg].colorize(:light_red)
|
17
|
+
stream.puts(msg)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Helmsnap::Generate
|
4
|
+
def self.call(...)
|
5
|
+
new(...).call
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(chart_path:, snapshots_path:, values_path:)
|
9
|
+
self.chart_path = chart_path
|
10
|
+
self.snapshots_path = snapshots_path
|
11
|
+
self.values_path = values_path
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
dep_list = run_cmd("helm", "dependency", "list", "--max-col-width", 0, chart_path).output
|
16
|
+
|
17
|
+
dep_list.scan(%r{file://(.+?)\t}) do |dep_path|
|
18
|
+
run_cmd("helm", "dependency", "update", "--skip-refresh", chart_path.join(dep_path.first))
|
19
|
+
end
|
20
|
+
|
21
|
+
dep_list.scan(%r{(https?://.+?)\t}) do |dep_path|
|
22
|
+
run_cmd("helm", "repo", "add", Digest::MD5.hexdigest(dep_path.first), dep_path.first)
|
23
|
+
end
|
24
|
+
|
25
|
+
run_cmd("helm", "dependency", "update", "--skip-refresh", chart_path)
|
26
|
+
|
27
|
+
FileUtils.rmtree(snapshots_path)
|
28
|
+
|
29
|
+
run_cmd(
|
30
|
+
"helm", "template", chart_path, "--values", values_path, "--output-dir", snapshots_path
|
31
|
+
)
|
32
|
+
|
33
|
+
snapshots_path.glob(["**/*yaml", "**/*.yml"]).each do |path|
|
34
|
+
content = path.read
|
35
|
+
content.gsub!(/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d+/, "2022-01-01 00:00:00.000") or next
|
36
|
+
path.write(content)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
attr_accessor :chart_path, :snapshots_path, :values_path
|
43
|
+
|
44
|
+
def run_cmd(...)
|
45
|
+
Helmsnap.run_cmd(...)
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Helmsnap::Runner
|
4
|
+
def self.call(...)
|
5
|
+
new(...).call
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(args)
|
9
|
+
self.args = args.dup
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
parser = Helmsnap::ArgsParser.new(args)
|
14
|
+
self.options = parser.get_options!
|
15
|
+
|
16
|
+
cmd, *rest = args
|
17
|
+
|
18
|
+
if cmd.nil?
|
19
|
+
parser.print_help!("Command not provided.")
|
20
|
+
end
|
21
|
+
|
22
|
+
if rest.size.positive?
|
23
|
+
parser.print_help!("Too many arguments.")
|
24
|
+
end
|
25
|
+
|
26
|
+
case cmd
|
27
|
+
when "generate"
|
28
|
+
generate!
|
29
|
+
when "check"
|
30
|
+
check!
|
31
|
+
else
|
32
|
+
parser.print_help!("Unknown command: #{cmd}.")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
attr_accessor :args, :options
|
39
|
+
|
40
|
+
def generate!
|
41
|
+
Helmsnap::Generate.call(**options.to_h)
|
42
|
+
Helmsnap::Console.info($stdout, "Snapshots generated successfully.")
|
43
|
+
end
|
44
|
+
|
45
|
+
def check!
|
46
|
+
if Helmsnap::Check.call(**options.to_h)
|
47
|
+
Helmsnap::Console.info($stdout, "Snapshots are up-to-date.")
|
48
|
+
else
|
49
|
+
example_cmd = Shellwords.join(
|
50
|
+
[
|
51
|
+
"helmsnap", "generate",
|
52
|
+
"--chart-dir", options.chart_path,
|
53
|
+
"--snapshots-dir", options.snapshots_path,
|
54
|
+
"--values", options.values_path
|
55
|
+
],
|
56
|
+
)
|
57
|
+
|
58
|
+
Helmsnap::Console.error(
|
59
|
+
$stdout,
|
60
|
+
"Snapshots are outdated. You should check the diff above and either fix your chart or " \
|
61
|
+
"update the snapshots using the following command:\n> #{example_cmd}",
|
62
|
+
)
|
63
|
+
|
64
|
+
exit 1
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/helmsnap/version.rb
CHANGED
data/lib/helmsnap.rb
CHANGED
@@ -1,7 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "digest"
|
4
|
+
require "fileutils"
|
5
|
+
require "open3"
|
6
|
+
require "optparse"
|
7
|
+
require "pathname"
|
8
|
+
require "shellwords"
|
9
|
+
require "tmpdir"
|
10
|
+
|
11
|
+
require "colorized_string"
|
4
12
|
|
5
13
|
module Helmsnap
|
14
|
+
require_relative "helmsnap/args_parser"
|
15
|
+
require_relative "helmsnap/check"
|
16
|
+
require_relative "helmsnap/console"
|
17
|
+
require_relative "helmsnap/command"
|
18
|
+
require_relative "helmsnap/generate"
|
19
|
+
require_relative "helmsnap/runner"
|
20
|
+
require_relative "helmsnap/version"
|
21
|
+
|
6
22
|
class Error < StandardError; end
|
23
|
+
|
24
|
+
def self.run_cmd(*cmd_parts, **options)
|
25
|
+
cmd = Shellwords.join(cmd_parts)
|
26
|
+
Helmsnap::Command.call(cmd, **options)
|
27
|
+
end
|
7
28
|
end
|
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: helmsnap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yuri Smirnov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11-
|
12
|
-
dependencies:
|
11
|
+
date: 2021-11-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colorize
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rubocop-config-umbrellio
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
13
41
|
description:
|
14
42
|
email:
|
15
43
|
- tycooon@yandex.ru
|
@@ -18,17 +46,26 @@ executables:
|
|
18
46
|
extensions: []
|
19
47
|
extra_rdoc_files: []
|
20
48
|
files:
|
49
|
+
- ".dockerignore"
|
21
50
|
- ".rspec"
|
22
51
|
- ".rubocop.yml"
|
52
|
+
- Dockerfile
|
23
53
|
- Gemfile
|
24
54
|
- Gemfile.lock
|
25
55
|
- LICENSE.txt
|
26
56
|
- README.md
|
27
57
|
- Rakefile
|
28
58
|
- bin/console
|
59
|
+
- bin/setup
|
29
60
|
- exe/helmsnap
|
30
61
|
- helmsnap.gemspec
|
31
62
|
- lib/helmsnap.rb
|
63
|
+
- lib/helmsnap/args_parser.rb
|
64
|
+
- lib/helmsnap/check.rb
|
65
|
+
- lib/helmsnap/command.rb
|
66
|
+
- lib/helmsnap/console.rb
|
67
|
+
- lib/helmsnap/generate.rb
|
68
|
+
- lib/helmsnap/runner.rb
|
32
69
|
- lib/helmsnap/version.rb
|
33
70
|
homepage: https://github.com/tycooon/helmsnap
|
34
71
|
licenses:
|
@@ -44,14 +81,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
44
81
|
requirements:
|
45
82
|
- - ">="
|
46
83
|
- !ruby/object:Gem::Version
|
47
|
-
version: 2.
|
84
|
+
version: 2.7.0
|
48
85
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
86
|
requirements:
|
50
87
|
- - ">="
|
51
88
|
- !ruby/object:Gem::Version
|
52
89
|
version: '0'
|
53
90
|
requirements: []
|
54
|
-
rubygems_version: 3.2.
|
91
|
+
rubygems_version: 3.2.32
|
55
92
|
signing_key:
|
56
93
|
specification_version: 4
|
57
94
|
summary: A tool for creating and checking helm chart snapshots.
|