helmsnap 0.5.1 → 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/Dockerfile +2 -1
- data/Gemfile.lock +4 -4
- data/README.md +22 -5
- data/lib/helmsnap/args_parser.rb +7 -21
- data/lib/helmsnap/check.rb +5 -11
- data/lib/helmsnap/config.rb +28 -0
- data/lib/helmsnap/env.rb +19 -0
- data/lib/helmsnap/generate.rb +19 -10
- data/lib/helmsnap/runner.rb +5 -11
- data/lib/helmsnap/version.rb +1 -1
- data/lib/helmsnap.rb +3 -0
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00d1a53c6e09960c8a7b6d21e9998aba27e0765959b4450f2e433754440fe65b
|
4
|
+
data.tar.gz: 0f9fc47f9897eb76745e817528646ac340e43e39fad563a8370560bde810274f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d014a938da2ea497e3e751f5cb600940ccb77a1d7bd297399a7b3380ac74c2d5a47bb9b4c31f6a540992c72d3e1012540d19b264e49d3498ffc282cb4f63b68a
|
7
|
+
data.tar.gz: 17614166a76919b0353d7bf322062047c546c3256826758ef5d0991bf66e30ee7ad0552c117ebad489ecba205e7c4771340dde7c947975cd1101895954eb8fe9
|
data/Dockerfile
CHANGED
@@ -2,8 +2,9 @@ FROM alpine/helm
|
|
2
2
|
|
3
3
|
RUN apk add --update --no-cache ruby git colordiff
|
4
4
|
|
5
|
-
WORKDIR /
|
5
|
+
WORKDIR /wd
|
6
6
|
|
7
|
+
COPY --from=quay.io/roboll/helmfile:v0.142.0 /usr/local/bin/helmfile /usr/local/bin/helmfile
|
7
8
|
COPY . .
|
8
9
|
|
9
10
|
RUN gem install colorize && gem build && gem install helmsnap --local
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
helmsnap (0.
|
4
|
+
helmsnap (0.6.0)
|
5
5
|
colorize
|
6
6
|
|
7
7
|
GEM
|
@@ -23,7 +23,7 @@ GEM
|
|
23
23
|
method_source (1.0.0)
|
24
24
|
minitest (5.14.4)
|
25
25
|
parallel (1.21.0)
|
26
|
-
parser (3.0.3.
|
26
|
+
parser (3.0.3.1)
|
27
27
|
ast (~> 2.4.1)
|
28
28
|
pry (0.14.1)
|
29
29
|
coderay (~> 1.1)
|
@@ -31,7 +31,7 @@ GEM
|
|
31
31
|
rack (2.2.3)
|
32
32
|
rainbow (3.0.0)
|
33
33
|
rake (13.0.6)
|
34
|
-
regexp_parser (2.
|
34
|
+
regexp_parser (2.2.0)
|
35
35
|
rexml (3.2.5)
|
36
36
|
rspec (3.10.0)
|
37
37
|
rspec-core (~> 3.10.0)
|
@@ -55,7 +55,7 @@ GEM
|
|
55
55
|
rubocop-ast (>= 1.7.0, < 2.0)
|
56
56
|
ruby-progressbar (~> 1.7)
|
57
57
|
unicode-display_width (>= 1.4.0, < 3.0)
|
58
|
-
rubocop-ast (1.
|
58
|
+
rubocop-ast (1.14.0)
|
59
59
|
parser (>= 3.0.1.1)
|
60
60
|
rubocop-config-umbrellio (1.17.0.53)
|
61
61
|
rubocop (= 1.17.0)
|
data/README.md
CHANGED
@@ -4,16 +4,16 @@
|
|
4
4
|
|
5
5
|
Helmsnap is a tool for generating and checking helm chart snapshots. Example:
|
6
6
|
|
7
|
-
Generate snapshots (uses `
|
7
|
+
Generate snapshots (uses `helmfile template` under the hood):
|
8
8
|
|
9
9
|
```sh
|
10
|
-
helmsnap generate
|
10
|
+
helmsnap generate
|
11
11
|
```
|
12
12
|
|
13
|
-
Generate snapshots in
|
13
|
+
Generate snapshots in a temporary directory and check (diff) them against existing snapshots in `helm/snapshots` directory:
|
14
14
|
|
15
15
|
```sh
|
16
|
-
helmsnap check
|
16
|
+
helmsnap check
|
17
17
|
```
|
18
18
|
|
19
19
|
Get the full description of possible arguments:
|
@@ -30,6 +30,23 @@ The typical usage flow:
|
|
30
30
|
|
31
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.
|
32
32
|
|
33
|
+
## Configuration
|
34
|
+
|
35
|
+
By default, helmsnap will render your helmfile using `default` environment and will place snapshots in `helm/snapshots` directory. If you want to configure that, create a `.helmsnap.yaml` file and put there configuration that looks like this:
|
36
|
+
|
37
|
+
```yaml
|
38
|
+
envs: [staging, production] # `[default]` by default
|
39
|
+
snapshotsPath: somedir/snapshots # `helm/snapshots` by default
|
40
|
+
```
|
41
|
+
|
42
|
+
You can also override configuration file location using `--config` option.
|
43
|
+
|
44
|
+
## Dependencies
|
45
|
+
|
46
|
+
- Ruby 2.7+.
|
47
|
+
- [Helmfile](https://github.com/roboll/helmfile), which in turn relies on [Helm](https://github.com/helm/helm).
|
48
|
+
- Colordiff or diff utility.
|
49
|
+
|
33
50
|
## Features
|
34
51
|
|
35
52
|
### Helm dependency management
|
@@ -58,7 +75,7 @@ Example job for Gitlab CI:
|
|
58
75
|
check-snapshots:
|
59
76
|
stage: test
|
60
77
|
image: ghcr.io/tycooon/helmsnap:latest
|
61
|
-
script: helmsnap check
|
78
|
+
script: helmsnap check
|
62
79
|
```
|
63
80
|
|
64
81
|
## Contributing
|
data/lib/helmsnap/args_parser.rb
CHANGED
@@ -1,22 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Helmsnap::ArgsParser
|
4
|
-
Args = Struct.new(:
|
5
|
-
MissingOption = Class.new(OptionParser::ParseError)
|
4
|
+
Args = Struct.new(:config_path)
|
6
5
|
|
6
|
+
DEFAULT_CONFIG_PATH = ".helmsnap.yaml"
|
7
|
+
CONFIG_PATH_HELP = %{Path to config (default: "#{DEFAULT_CONFIG_PATH}")}
|
7
8
|
BANNER = "Usage: helmsnap CMD [options]"
|
8
9
|
|
9
10
|
def initialize(options)
|
10
11
|
self.options = options
|
11
|
-
self.args = Args.new
|
12
|
+
self.args = Args.new(DEFAULT_CONFIG_PATH)
|
12
13
|
self.parser = build_parser
|
13
14
|
end
|
14
15
|
|
15
16
|
def get_options!
|
16
17
|
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
18
|
args
|
21
19
|
rescue OptionParser::ParseError => error
|
22
20
|
print_help!(error)
|
@@ -32,22 +30,14 @@ class Helmsnap::ArgsParser
|
|
32
30
|
|
33
31
|
attr_accessor :options, :parser, :args
|
34
32
|
|
35
|
-
def build_parser
|
33
|
+
def build_parser
|
36
34
|
OptionParser.new(BANNER, 50) do |opts|
|
37
35
|
opts.separator("Supported commands: `generate` and `check`.")
|
38
36
|
opts.separator("")
|
39
37
|
opts.separator("Specific options:")
|
40
38
|
|
41
|
-
opts.on("-c", "--
|
42
|
-
args.
|
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)
|
39
|
+
opts.on("-c", "--config CONFIG_PATH", CONFIG_PATH_HELP) do |val|
|
40
|
+
args.config_path = Pathname.new(val)
|
51
41
|
end
|
52
42
|
|
53
43
|
opts.on("--version", "Show version") do
|
@@ -61,8 +51,4 @@ class Helmsnap::ArgsParser
|
|
61
51
|
end
|
62
52
|
end
|
63
53
|
end
|
64
|
-
|
65
|
-
def pn(...)
|
66
|
-
Pathname.new(...)
|
67
|
-
end
|
68
54
|
end
|
data/lib/helmsnap/check.rb
CHANGED
@@ -1,26 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Helmsnap::Check < Helmsnap::Service
|
4
|
-
def initialize(
|
4
|
+
def initialize(config)
|
5
5
|
super()
|
6
|
-
self.
|
7
|
-
self.snapshots_path = snapshots_path
|
8
|
-
self.values_path = values_path
|
6
|
+
self.config = config
|
9
7
|
end
|
10
8
|
|
11
9
|
def call
|
12
10
|
temp_dir_path = Pathname.new(Dir.mktmpdir)
|
13
11
|
|
14
|
-
Helmsnap::Generate.call(
|
15
|
-
chart_path: chart_path,
|
16
|
-
snapshots_path: temp_dir_path,
|
17
|
-
values_path: values_path,
|
18
|
-
)
|
12
|
+
Helmsnap::Generate.call(config, snapshots_path: temp_dir_path)
|
19
13
|
|
20
14
|
result = run_cmd("which", "colordiff", allow_failure: true)
|
21
15
|
util = result.success ? "colordiff" : "diff"
|
22
16
|
|
23
|
-
cmd_parts = [util, "--unified", "--recursive", snapshots_path, temp_dir_path]
|
17
|
+
cmd_parts = [util, "--unified", "--recursive", config.snapshots_path, temp_dir_path]
|
24
18
|
diff = run_cmd(*cmd_parts, allow_failure: true).output
|
25
19
|
|
26
20
|
diff.strip.empty?
|
@@ -30,5 +24,5 @@ class Helmsnap::Check < Helmsnap::Service
|
|
30
24
|
|
31
25
|
private
|
32
26
|
|
33
|
-
attr_accessor :
|
27
|
+
attr_accessor :config
|
34
28
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Helmsnap::Config
|
4
|
+
attr_reader :envs, :snapshots_path
|
5
|
+
|
6
|
+
DEFAULT_ENV = "default"
|
7
|
+
|
8
|
+
def initialize(config_path)
|
9
|
+
yaml = YAML.load_file(config_path.to_s)
|
10
|
+
self.envs = parse_envs(yaml)
|
11
|
+
self.snapshots_path = parse_snaphots_path(yaml)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_writer :envs, :snapshots_path
|
17
|
+
|
18
|
+
def parse_envs(yaml)
|
19
|
+
# TODO: check value type
|
20
|
+
value = yaml.fetch("envs", [DEFAULT_ENV])
|
21
|
+
value.map { |x| Helmsnap::Env.new(x) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse_snaphots_path(yaml)
|
25
|
+
# TODO: chekc value type/presence
|
26
|
+
Pathname.new(yaml.fetch("snapshotsPath"))
|
27
|
+
end
|
28
|
+
end
|
data/lib/helmsnap/env.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Helmsnap::Env
|
4
|
+
attr_reader :name, :release_paths
|
5
|
+
|
6
|
+
def initialize(name)
|
7
|
+
self.name = name
|
8
|
+
self.release_paths = get_release_paths
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
attr_writer :name, :release_paths
|
14
|
+
|
15
|
+
def get_release_paths
|
16
|
+
json = Helmsnap.run_cmd("helmfile", "--environment", name, "list", "--output", "json").output
|
17
|
+
YAML.load(json).map { |x| x.fetch("chart") }
|
18
|
+
end
|
19
|
+
end
|
data/lib/helmsnap/generate.rb
CHANGED
@@ -1,21 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Helmsnap::Generate < Helmsnap::Service
|
4
|
-
def initialize(
|
4
|
+
def initialize(config, snapshots_path: nil)
|
5
5
|
super()
|
6
|
-
self.
|
7
|
-
self.snapshots_path = snapshots_path
|
8
|
-
self.values_path = values_path
|
6
|
+
self.config = config
|
7
|
+
self.snapshots_path = snapshots_path || config.snapshots_path
|
9
8
|
end
|
10
9
|
|
11
10
|
def call
|
12
|
-
Helmsnap::SetupDependencies.call(chart_path)
|
13
|
-
|
14
11
|
FileUtils.rmtree(snapshots_path)
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
config.envs.flat_map(&:release_paths).uniq.each do |release_path|
|
14
|
+
Helmsnap::SetupDependencies.call(release_path)
|
15
|
+
end
|
16
|
+
|
17
|
+
config.envs.each do |env|
|
18
|
+
run_cmd(
|
19
|
+
"helmfile",
|
20
|
+
"--environment",
|
21
|
+
env.name,
|
22
|
+
"template",
|
23
|
+
"--output-dir-template",
|
24
|
+
snapshots_path.join(env.name).join("{{ .Release.Name }}"),
|
25
|
+
"--skip-deps",
|
26
|
+
)
|
27
|
+
end
|
19
28
|
|
20
29
|
snapshots_path.glob(["**/*yaml", "**/*.yml"]).each do |path|
|
21
30
|
content = path.read
|
@@ -26,5 +35,5 @@ class Helmsnap::Generate < Helmsnap::Service
|
|
26
35
|
|
27
36
|
private
|
28
37
|
|
29
|
-
attr_accessor :
|
38
|
+
attr_accessor :config, :snapshots_path
|
30
39
|
end
|
data/lib/helmsnap/runner.rb
CHANGED
@@ -9,6 +9,7 @@ class Helmsnap::Runner < Helmsnap::Service
|
|
9
9
|
def call
|
10
10
|
parser = Helmsnap::ArgsParser.new(args)
|
11
11
|
self.options = parser.get_options!
|
12
|
+
self.config = Helmsnap::Config.new(options.config_path)
|
12
13
|
|
13
14
|
cmd, *rest = args
|
14
15
|
|
@@ -32,25 +33,18 @@ class Helmsnap::Runner < Helmsnap::Service
|
|
32
33
|
|
33
34
|
private
|
34
35
|
|
35
|
-
attr_accessor :args, :options
|
36
|
+
attr_accessor :args, :options, :config
|
36
37
|
|
37
38
|
def generate!
|
38
|
-
Helmsnap::Generate.call(
|
39
|
+
Helmsnap::Generate.call(config)
|
39
40
|
Helmsnap::Console.info($stdout, "Snapshots generated successfully.")
|
40
41
|
end
|
41
42
|
|
42
43
|
def check!
|
43
|
-
if Helmsnap::Check.call(
|
44
|
+
if Helmsnap::Check.call(config)
|
44
45
|
Helmsnap::Console.info($stdout, "Snapshots are up-to-date.")
|
45
46
|
else
|
46
|
-
example_cmd = Shellwords.join(
|
47
|
-
[
|
48
|
-
"helmsnap", "generate",
|
49
|
-
"--chart-dir", options.chart_path,
|
50
|
-
"--snapshots-dir", options.snapshots_path,
|
51
|
-
"--values", options.values_path
|
52
|
-
],
|
53
|
-
)
|
47
|
+
example_cmd = Shellwords.join(["helmsnap", "generate", "--config", options.config_path])
|
54
48
|
|
55
49
|
Helmsnap::Console.error(
|
56
50
|
$stdout,
|
data/lib/helmsnap/version.rb
CHANGED
data/lib/helmsnap.rb
CHANGED
@@ -7,10 +7,13 @@ require "optparse"
|
|
7
7
|
require "pathname"
|
8
8
|
require "shellwords"
|
9
9
|
require "tmpdir"
|
10
|
+
require "yaml"
|
10
11
|
|
11
12
|
require "colorized_string"
|
12
13
|
|
13
14
|
module Helmsnap
|
15
|
+
require_relative "helmsnap/config"
|
16
|
+
require_relative "helmsnap/env"
|
14
17
|
require_relative "helmsnap/service"
|
15
18
|
require_relative "helmsnap/version"
|
16
19
|
|
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.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yuri Smirnov
|
@@ -63,7 +63,9 @@ files:
|
|
63
63
|
- lib/helmsnap/args_parser.rb
|
64
64
|
- lib/helmsnap/check.rb
|
65
65
|
- lib/helmsnap/command.rb
|
66
|
+
- lib/helmsnap/config.rb
|
66
67
|
- lib/helmsnap/console.rb
|
68
|
+
- lib/helmsnap/env.rb
|
67
69
|
- lib/helmsnap/generate.rb
|
68
70
|
- lib/helmsnap/runner.rb
|
69
71
|
- lib/helmsnap/service.rb
|