helmsnap 0.2.0 → 0.3.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/.dockerignore +8 -0
- data/Dockerfile +12 -0
- data/Gemfile.lock +5 -2
- data/README.md +47 -16
- data/bin/setup +0 -0
- data/helmsnap.gemspec +2 -0
- data/lib/helmsnap/args_parser.rb +12 -6
- data/lib/helmsnap/check.rb +6 -2
- data/lib/helmsnap/command.rb +24 -14
- data/lib/helmsnap/console.rb +19 -0
- data/lib/helmsnap/generate.rb +7 -7
- data/lib/helmsnap/runner.rb +23 -4
- data/lib/helmsnap/version.rb +1 -1
- data/lib/helmsnap.rb +5 -2
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 926b5a2923e842e0fe10f3d2050e785a0a140edbb0c3de40c30880e9e7dac3ba
|
4
|
+
data.tar.gz: 5f99aaac6f14b66727365bbde866896f9c75bd98e129d48de07d76ebdd7ff6a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ba861f010040454c80b4413f3b5e7b74213e0ad041f6c8311ca8295bfb06b71a04a98323f2b6714691e2450f0ce54897ff340a2534cfa66cd79f73884741614
|
7
|
+
data.tar.gz: 4e164358cf3084a01fc026fcf44670939c6871035883afde758624f31b31739a6fc48d610e9a6a81204fef8535e9c417c95e705c02998a07edf7913e28a16745
|
data/.dockerignore
ADDED
data/Dockerfile
ADDED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
helmsnap (0.
|
4
|
+
helmsnap (0.3.0)
|
5
|
+
colorize
|
5
6
|
|
6
7
|
GEM
|
7
8
|
remote: https://rubygems.org/
|
@@ -14,6 +15,7 @@ GEM
|
|
14
15
|
zeitwerk (~> 2.3)
|
15
16
|
ast (2.4.2)
|
16
17
|
coderay (1.1.3)
|
18
|
+
colorize (0.8.1)
|
17
19
|
concurrent-ruby (1.1.9)
|
18
20
|
diff-lcs (1.4.4)
|
19
21
|
i18n (1.8.11)
|
@@ -84,6 +86,7 @@ GEM
|
|
84
86
|
|
85
87
|
PLATFORMS
|
86
88
|
x86_64-darwin-20
|
89
|
+
x86_64-linux
|
87
90
|
|
88
91
|
DEPENDENCIES
|
89
92
|
helmsnap!
|
@@ -94,4 +97,4 @@ DEPENDENCIES
|
|
94
97
|
rubocop-config-umbrellio
|
95
98
|
|
96
99
|
BUNDLED WITH
|
97
|
-
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
|
+
```
|
8
12
|
|
9
|
-
|
13
|
+
Generate snapshots in some temp directory and check (diff) them against existing snapshots in `helm/snapshots` directory:
|
10
14
|
|
11
|
-
```
|
12
|
-
|
15
|
+
```sh
|
16
|
+
helmsnap check -c helm/mychart -s helm/snapshots -v helm/values/production.yaml
|
13
17
|
```
|
14
18
|
|
15
|
-
|
19
|
+
Get the full description of possible arguments:
|
20
|
+
|
21
|
+
```sh
|
22
|
+
helmsnap --help
|
23
|
+
```
|
24
|
+
|
25
|
+
The typical usage flow:
|
26
|
+
|
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`.
|
16
30
|
|
17
|
-
|
31
|
+
## Features
|
18
32
|
|
19
|
-
|
33
|
+
### Helm dependency management
|
20
34
|
|
21
|
-
|
35
|
+
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.
|
22
36
|
|
23
|
-
|
37
|
+
### Timestamp replacement
|
24
38
|
|
25
|
-
|
39
|
+
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.
|
26
40
|
|
27
|
-
##
|
41
|
+
## Installation
|
42
|
+
|
43
|
+
Just install a gem and use the provided `helmsnap` binary.
|
44
|
+
|
45
|
+
```sh
|
46
|
+
gem install helmsnap
|
47
|
+
```
|
28
48
|
|
29
|
-
|
49
|
+
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.
|
30
50
|
|
31
|
-
|
51
|
+
## CI example
|
52
|
+
|
53
|
+
Example job for Gitlab CI:
|
54
|
+
|
55
|
+
```yaml
|
56
|
+
check-snapshots:
|
57
|
+
stage: test
|
58
|
+
image:
|
59
|
+
name: ghcr.io/tycooon/helmsnap:master
|
60
|
+
entrypoint: []
|
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
CHANGED
File without changes
|
data/helmsnap.gemspec
CHANGED
data/lib/helmsnap/args_parser.rb
CHANGED
@@ -4,6 +4,8 @@ class Helmsnap::ArgsParser
|
|
4
4
|
Args = Struct.new(:chart_path, :snapshots_path, :values_path, keyword_init: true)
|
5
5
|
MissingOption = Class.new(OptionParser::ParseError)
|
6
6
|
|
7
|
+
BANNER = "Usage: helmsnap CMD [options]"
|
8
|
+
|
7
9
|
def initialize(options)
|
8
10
|
self.options = options
|
9
11
|
self.args = Args.new
|
@@ -21,8 +23,8 @@ class Helmsnap::ArgsParser
|
|
21
23
|
end
|
22
24
|
|
23
25
|
def print_help!(msg)
|
24
|
-
|
25
|
-
|
26
|
+
Helmsnap::Console.error($stderr, "#{msg}\n") if msg
|
27
|
+
Helmsnap::Console.print($stdout, parser.help)
|
26
28
|
exit 1
|
27
29
|
end
|
28
30
|
|
@@ -30,9 +32,8 @@ class Helmsnap::ArgsParser
|
|
30
32
|
|
31
33
|
attr_accessor :options, :parser, :args
|
32
34
|
|
33
|
-
def build_parser
|
34
|
-
OptionParser.new do |opts|
|
35
|
-
opts.banner = "Usage: helmsnap CMD [options]"
|
35
|
+
def build_parser # rubocop:disable Metrics/MethodLength
|
36
|
+
OptionParser.new(BANNER, 50) do |opts|
|
36
37
|
opts.separator("Supported commands: `generate` and `check`.")
|
37
38
|
opts.separator("")
|
38
39
|
opts.separator("Specific options:")
|
@@ -49,8 +50,13 @@ class Helmsnap::ArgsParser
|
|
49
50
|
args.values_path = pn(option)
|
50
51
|
end
|
51
52
|
|
53
|
+
opts.on("--version", "Show version") do
|
54
|
+
Helmsnap::Console.print($stdout, "#{Helmsnap::VERSION}\n")
|
55
|
+
exit
|
56
|
+
end
|
57
|
+
|
52
58
|
opts.on("-h", "--help", "Show this message") do
|
53
|
-
|
59
|
+
print_help!(nil)
|
54
60
|
exit
|
55
61
|
end
|
56
62
|
end
|
data/lib/helmsnap/check.rb
CHANGED
@@ -13,7 +13,7 @@ class Helmsnap::Check
|
|
13
13
|
|
14
14
|
def call
|
15
15
|
Dir.mktmpdir do |temp_dir|
|
16
|
-
|
16
|
+
temp_dir_path = Pathname.new(temp_dir)
|
17
17
|
|
18
18
|
Helmsnap::Generate.call(
|
19
19
|
chart_path: chart_path,
|
@@ -21,7 +21,11 @@ class Helmsnap::Check
|
|
21
21
|
values_path: values_path,
|
22
22
|
)
|
23
23
|
|
24
|
-
Helmsnap.run_cmd
|
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?
|
25
29
|
end
|
26
30
|
end
|
27
31
|
|
data/lib/helmsnap/command.rb
CHANGED
@@ -1,38 +1,48 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Helmsnap::Command
|
4
|
+
Result = Struct.new(:success, :output)
|
5
|
+
|
4
6
|
def self.call(...)
|
5
7
|
new(...).call
|
6
8
|
end
|
7
9
|
|
8
|
-
def initialize(cmd)
|
10
|
+
def initialize(cmd, stdout: $stdout, stderr: $stderr, allow_failure: false)
|
9
11
|
self.cmd = cmd
|
12
|
+
self.stdout = stdout
|
13
|
+
self.stderr = stderr
|
14
|
+
self.allow_failure = allow_failure
|
10
15
|
end
|
11
16
|
|
12
17
|
def call
|
13
|
-
|
18
|
+
Helmsnap::Console.info(stdout, "> #{cmd}")
|
19
|
+
run_command
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
14
23
|
|
15
|
-
|
24
|
+
attr_accessor :cmd, :stdout, :stderr, :allow_failure
|
25
|
+
|
26
|
+
def run_command
|
27
|
+
Open3.popen3(cmd) do |_in, out, err, wait_thr|
|
16
28
|
output = +""
|
17
29
|
|
18
|
-
while (chunk =
|
19
|
-
|
30
|
+
while (chunk = out.gets)
|
31
|
+
Helmsnap::Console.print(stdout, chunk)
|
20
32
|
output << chunk
|
21
33
|
end
|
22
34
|
|
23
35
|
exit_status = wait_thr.value
|
36
|
+
success = exit_status.success?
|
24
37
|
|
25
|
-
|
26
|
-
|
27
|
-
|
38
|
+
if !success && !allow_failure
|
39
|
+
Helmsnap::Console.error(stderr, err.read, :red)
|
40
|
+
Helmsnap::Console.error(stderr, "Command failed with status #{exit_status.to_i}", :red)
|
41
|
+
abort
|
28
42
|
end
|
29
43
|
|
30
|
-
|
31
|
-
output
|
44
|
+
Helmsnap::Console.print(stdout, "\n")
|
45
|
+
Result.new(success, output)
|
32
46
|
end
|
33
47
|
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
attr_accessor :cmd
|
38
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
|
data/lib/helmsnap/generate.rb
CHANGED
@@ -12,21 +12,21 @@ class Helmsnap::Generate
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def call
|
15
|
-
dep_list = run_cmd
|
15
|
+
dep_list = run_cmd("helm", "dependency", "list", "--max-col-width", 0, chart_path).output
|
16
16
|
|
17
17
|
dep_list.scan(%r{file://(.+?)\t}) do |dep_path|
|
18
|
-
run_cmd
|
18
|
+
run_cmd("helm", "dependency", "update", "--skip-refresh", chart_path.join(dep_path.first))
|
19
19
|
end
|
20
20
|
|
21
21
|
dep_list.scan(%r{(https?://.+?)\t}) do |dep_path|
|
22
|
-
run_cmd
|
22
|
+
run_cmd("helm", "repo", "add", Digest::MD5.hexdigest(dep_path.first), dep_path.first)
|
23
23
|
end
|
24
24
|
|
25
|
-
run_cmd
|
25
|
+
run_cmd("helm", "dependency", "update", "--skip-refresh", chart_path)
|
26
26
|
|
27
27
|
FileUtils.rmtree(snapshots_path)
|
28
28
|
|
29
|
-
run_cmd
|
29
|
+
run_cmd(
|
30
30
|
"helm", "template", chart_path, "--values", values_path, "--output-dir", snapshots_path
|
31
31
|
)
|
32
32
|
|
@@ -41,7 +41,7 @@ class Helmsnap::Generate
|
|
41
41
|
|
42
42
|
attr_accessor :chart_path, :snapshots_path, :values_path
|
43
43
|
|
44
|
-
def run_cmd
|
45
|
-
Helmsnap.run_cmd
|
44
|
+
def run_cmd(...)
|
45
|
+
Helmsnap.run_cmd(...)
|
46
46
|
end
|
47
47
|
end
|
data/lib/helmsnap/runner.rb
CHANGED
@@ -11,7 +11,7 @@ class Helmsnap::Runner
|
|
11
11
|
|
12
12
|
def call
|
13
13
|
parser = Helmsnap::ArgsParser.new(args)
|
14
|
-
options = parser.get_options!
|
14
|
+
self.options = parser.get_options!
|
15
15
|
|
16
16
|
cmd, *rest = args
|
17
17
|
|
@@ -25,9 +25,9 @@ class Helmsnap::Runner
|
|
25
25
|
|
26
26
|
case cmd
|
27
27
|
when "generate"
|
28
|
-
|
28
|
+
generate!
|
29
29
|
when "check"
|
30
|
-
|
30
|
+
check!
|
31
31
|
else
|
32
32
|
parser.print_help!("Unknown command: #{cmd}.")
|
33
33
|
end
|
@@ -35,5 +35,24 @@ class Helmsnap::Runner
|
|
35
35
|
|
36
36
|
private
|
37
37
|
|
38
|
-
attr_accessor :args
|
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
|
+
Helmsnap::Console.error(
|
50
|
+
$stdout,
|
51
|
+
"Snapshots are outdated, you should check the diff above and either fix your chart or " \
|
52
|
+
"update the snapshots using `helmsnap generate` command.",
|
53
|
+
)
|
54
|
+
|
55
|
+
exit 1
|
56
|
+
end
|
57
|
+
end
|
39
58
|
end
|
data/lib/helmsnap/version.rb
CHANGED
data/lib/helmsnap.rb
CHANGED
@@ -8,9 +8,12 @@ require "pathname"
|
|
8
8
|
require "shellwords"
|
9
9
|
require "tmpdir"
|
10
10
|
|
11
|
+
require "colorized_string"
|
12
|
+
|
11
13
|
module Helmsnap
|
12
14
|
require_relative "helmsnap/args_parser"
|
13
15
|
require_relative "helmsnap/check"
|
16
|
+
require_relative "helmsnap/console"
|
14
17
|
require_relative "helmsnap/command"
|
15
18
|
require_relative "helmsnap/generate"
|
16
19
|
require_relative "helmsnap/runner"
|
@@ -18,8 +21,8 @@ module Helmsnap
|
|
18
21
|
|
19
22
|
class Error < StandardError; end
|
20
23
|
|
21
|
-
def self.run_cmd
|
24
|
+
def self.run_cmd(*cmd_parts, **options)
|
22
25
|
cmd = Shellwords.join(cmd_parts)
|
23
|
-
Helmsnap::Command.call(cmd)
|
26
|
+
Helmsnap::Command.call(cmd, **options)
|
24
27
|
end
|
25
28
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: helmsnap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yuri Smirnov
|
@@ -10,6 +10,20 @@ bindir: exe
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2021-11-27 00:00:00.000000000 Z
|
12
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'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rubocop-config-umbrellio
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -32,8 +46,10 @@ executables:
|
|
32
46
|
extensions: []
|
33
47
|
extra_rdoc_files: []
|
34
48
|
files:
|
49
|
+
- ".dockerignore"
|
35
50
|
- ".rspec"
|
36
51
|
- ".rubocop.yml"
|
52
|
+
- Dockerfile
|
37
53
|
- Gemfile
|
38
54
|
- Gemfile.lock
|
39
55
|
- LICENSE.txt
|
@@ -47,6 +63,7 @@ files:
|
|
47
63
|
- lib/helmsnap/args_parser.rb
|
48
64
|
- lib/helmsnap/check.rb
|
49
65
|
- lib/helmsnap/command.rb
|
66
|
+
- lib/helmsnap/console.rb
|
50
67
|
- lib/helmsnap/generate.rb
|
51
68
|
- lib/helmsnap/runner.rb
|
52
69
|
- lib/helmsnap/version.rb
|
@@ -71,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
88
|
- !ruby/object:Gem::Version
|
72
89
|
version: '0'
|
73
90
|
requirements: []
|
74
|
-
rubygems_version: 3.2.
|
91
|
+
rubygems_version: 3.2.32
|
75
92
|
signing_key:
|
76
93
|
specification_version: 4
|
77
94
|
summary: A tool for creating and checking helm chart snapshots.
|