rhelm 0.1.0.pre.alpha1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 32884b06d9fdc1fc9d86397f132ad9581ce7053165b33c275fe230dec6fc2d53
4
+ data.tar.gz: a030dd7932b5c252791db8b851de0f138118a21ca6af0426f728187c7c087ba4
5
+ SHA512:
6
+ metadata.gz: c59de0c7c7440bdff5511991fc091d15c0c2d3adcef87ac5006360ea07286ff9b408b1df303fa502b23dd40aa461c424cc76fa01d44cc0224455c6ddd26b4cc5
7
+ data.tar.gz: d7bdb9b76792f1019ad13947d937537fc08ecf9e3509268cba39616dd7a2b27eb7242b166bf71882335629c0a998d776d4a3ecb3a6c9b391f580e35483a49978
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ *.gem
10
+ Gemfile.lock
11
+ .ruby-version
12
+ .ruby-gemset
13
+ .byebug_history
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in helm.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "minitest", "~> 5.0"
8
+ gem "pry-byebug"
data/LICENSE.txt ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2021 Internet Brands
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,133 @@
1
+ # rhelm
2
+
3
+ Ruby wrapper around the [helm](helm.sh) binary. Pronounced "realm", because English is weird like that.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'rhelm'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install rhelm
20
+
21
+ ## Usage
22
+
23
+ Usage of Rhelm is simple:
24
+
25
+ 1. Configure a Rhelm::Client object with appropriate kubeconfig or API/token information so that you can talk to your k8s cluster
26
+ 2. Using the client object, invoke subcommands such as "install", "upgrade", "status", etc.
27
+
28
+ ### Creating the client
29
+
30
+ ```ruby
31
+
32
+ require 'rhelm/client'
33
+
34
+ # Using kubeconfig
35
+ cli = Rhelm::Client.new(kubeconfig: '/home/someone/.kube/config')
36
+
37
+ # Using explicit API and token details
38
+ cli = Rhelm::Client.new(kube_apiserver: 'http://localhost:8080/api', kube_token: 'verysecret')
39
+ ```
40
+
41
+ #### Logging
42
+ You can also pass a `logger:` kwarg. It should be an object that responds to `error`, `warn`, `info`, and `debug`. If you don't specify `logger:` then a default will be provided that logs to STDOUT at log level `info` and above. See [Rhelm::Client::SimpleLogger](lib/rhelm/client/simple_logger.rb)
43
+
44
+
45
+ ### Invoking a subcommand
46
+
47
+ Subcommands such as `helm install`, `helm pull`, etc. can be invoked in one of two ways:
48
+
49
+ * Via subcommand proxy:
50
+
51
+ ```ruby
52
+
53
+ cli = Rhelm::Client.new(kubeconfig: '/home/someone/.kube/config')
54
+ # .install creates a proxy to the ::Install subcommand; .run runs it
55
+ cli.install(
56
+ 'my-mysql-release',
57
+ 'bitnami/mysql',
58
+ values: 'my-values.yml'
59
+ ).run
60
+ ```
61
+
62
+ * Via direct subcommand object creation:
63
+
64
+ ```ruby
65
+ subcommand = Rhelm::Subcommand::Install.new(
66
+ 'my-mysql-release',
67
+ 'bitnami/mysql',
68
+ kubeconfig: '/home/someone/.kube/config',
69
+ values: 'my-values.yml'
70
+ )
71
+ subcommand.run
72
+ ```
73
+
74
+ The difference between creating subcommands via proxy and creating subcommand objects directly is that in the proxy case, client constructor kwargs (especially those related to authentication) will automatically propagate to all subcommands created by proxy.
75
+
76
+ Non-kwarg arguments (such as `my-mysql-release` and `bitnami/mysql` in the example above) are passed as arguments to the underlying command without modification.
77
+
78
+ For a complete list of subcommands, look at the subclasses of [Rhelm::Subcommand](lib/rhelm/subcommand).
79
+
80
+ ### Responding to helm exit status and output
81
+
82
+ When `.run` is called, the command is invoked and its exit status and stdout/stderr are captured. These are submitted to a callback for handling. You can provide a callback (as a block) to the `.run` call like this:
83
+
84
+ ```ruby
85
+ Rhelm::Client.new(kubeconfig: 'kube.cfg')
86
+ .install('my-release-name',
87
+ 'some-chart-dir').run do |lines, status|
88
+ if status == 0
89
+ logger.info("helm install worked great!")
90
+ elsif /timeout/im.match(lines)
91
+ raise MyTimeoutError, "helm install timed out, oh no!"
92
+ else
93
+ # Use the built-in error reporting code to get more details
94
+ report_failure(lines, status)
95
+ end
96
+ end
97
+ ```
98
+
99
+ This callback technique allows us to evaluate certain "error" conditions for semantic meaning and return more meaningful results instead of raising an error. See [Rhelm::Subcommand::Status#exists?](lib/rhelm/subcommand/status.rb) for example.
100
+
101
+ For some commands like `install` and `upgrade` that are not instant, you may want to wait until the entire command is completed before evaluating status. To do this, specify `helm` options to wait for completion using the `wait: true` and `timeout: timeref` kwargs for your subcommand. Otherwise you'll just get the exit status of the `helm` command that was submitted to the server and you'll need to poll (with the `::Status` subcommand) to find out whether the helm command actually succeeded.
102
+
103
+ ### Specifying the helm binary to be used
104
+
105
+ ```ruby
106
+ cli = Rhelm::Client.new(program: '/path/to/a/specific/helm/binary')
107
+ ```
108
+
109
+ By default `helm` (with no path specification) will be used.
110
+
111
+ ### Version Info
112
+
113
+ You can ask a client about the version of the `helm` binary it is using.
114
+
115
+ ```ruby
116
+ 2.7.1 :001 > cli = Rhelm::Client.new
117
+ 2.7.1 :002 > cli.helm_version
118
+ => "v3.4.2"
119
+ 2.7.1 :003 > cli.helm_commit
120
+ => "23dd3af5e19a02d4f4baa5b2f242645a1a3af629"
121
+ 2.7.1 :004 > cli.helm_go_version
122
+ => "go1.15.5"
123
+ ```
124
+
125
+ ## Development
126
+
127
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
128
+
129
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
130
+
131
+ ## Contributing
132
+
133
+ Bug reports and pull requests are welcome on GitHub at https://github.com/internetbrands/rhelm.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rhelm"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/rhelm.rb ADDED
@@ -0,0 +1,2 @@
1
+ require_relative "rhelm/version"
2
+ require_relative "rhelm/client"
@@ -0,0 +1,57 @@
1
+ require 'rhelm/client/simple_logger'
2
+ require 'rhelm/subcommand_proxy'
3
+
4
+ module Rhelm
5
+ class Client
6
+ class Error < StandardError; end
7
+
8
+ SUBCOMMANDS = %i(
9
+ dependency env history install pull rollback
10
+ status test uninstall upgrade verify version
11
+ )
12
+ SUBCOMMANDS.each { |s| require_relative "subcommand/#{s}" }
13
+
14
+ attr_reader :program, :logger
15
+
16
+ def initialize(program: "helm", logger: nil, **default_options)
17
+ @program = program
18
+ @logger ||= SimpleLogger.new
19
+ @default_options = default_options || {}
20
+ end
21
+
22
+ SUBCOMMANDS.each do |subcommand|
23
+ define_method subcommand do |*args, **kwargs, &block|
24
+ SubcommandProxy.new(subcommand, self, *args, **@default_options.merge(kwargs), &block)
25
+ end
26
+ end
27
+
28
+ def run_command(subcommand_name, *ordinal_options, **flag_options, &block)
29
+ SubcommandProxy.new(subcommand_name, self, *ordinal_options, **@default_options.merge(flag_options), &block).run
30
+ end
31
+
32
+ def helm_version
33
+ version_info[:Version]
34
+ end
35
+
36
+ def helm_commit
37
+ version_info[:GitCommit]
38
+ end
39
+
40
+ def helm_go_version
41
+ version_info[:GoVersion]
42
+ end
43
+
44
+ private
45
+
46
+ # version.BuildInfo{Version:"v3.4.2", GitCommit:"23dd3af5e19a02d4f4baa5b2f242645a1a3af629", GitTreeState:"dirty", GoVersion:"go1.15.5"}
47
+ HELM_VERSION_RE = /version\.BuildInfo\{Version:"([^"]+)", GitCommit:"([^"]+)", GitTreeState:"([^"]+)", GoVersion:"([^"]+)"\}/m.freeze
48
+ def version_info
49
+ @version_info ||=
50
+ version.run do |lines, status|
51
+ if m = HELM_VERSION_RE.match(lines)
52
+ { Version: m[1], GitCommit: m[2], GoVersion: m[4] }
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,19 @@
1
+ module Rhelm
2
+ class Client
3
+ class SimpleLogger
4
+ class Error < StandardError; end
5
+ LEVELS = { debug: 3, info: 2, warn: 1, error: 0 }
6
+ attr_accessor :level
7
+ def initialize(level = :info)
8
+ raise(Error, "unknown log level #{level}") unless LEVELS.key?(level)
9
+ @level = LEVELS[level]
10
+ end
11
+ LEVELS.keys.each do |l|
12
+ define_method l do |*args|
13
+ return unless level >= LEVELS[l]
14
+ puts "[#{l.to_s.upcase}] #{args.compact.map(&:to_s).join(' ')}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,82 @@
1
+ module Rhelm
2
+ module Subcommand
3
+ class Error < StandardError; end
4
+
5
+ ## Abstract base class for Helm subcommands.
6
+ class Base
7
+ class OptionError < StandardError; end
8
+
9
+ attr_reader :client,
10
+ :debug,
11
+ :kube_apiserver,
12
+ :kube_as_group,
13
+ :kube_as_user,
14
+ :kube_context,
15
+ :kube_token,
16
+ :kubeconfig,
17
+ :namespace,
18
+ :registry_config,
19
+ :repository_cache,
20
+ :repository_config
21
+
22
+ def initialize(options = {})
23
+ @client = options.delete(:client) || Client.new
24
+ @debug = options[:debug]
25
+ @kube_apiserver = options[:kube_apiserver]
26
+ @kube_as_group = options[:kube_as_group]
27
+ @kube_as_user = options[:kube_as_user]
28
+ @kube_context = options[:kube_context]
29
+ @kube_token = options[:kube_token]
30
+ @kubeconfig = options[:kubeconfig]
31
+ @namespace = options[:namespace]
32
+ @registry_config = options[:registry_config]
33
+ @repository_cache = options[:repository_cache]
34
+ @repository_config = options[:repository_config]
35
+ end
36
+
37
+ def run(client: nil, raise_on_error: true, &block)
38
+ b = block_given? ? block : Proc.new { |_lines, status| status }
39
+
40
+ lines, status = Open3.capture2e(*full_cli_call)
41
+ report_failure(lines, status.exitstatus) if raise_on_error && status.exitstatus != 0
42
+
43
+ b.yield lines, status.exitstatus
44
+ end
45
+
46
+ def cli_args
47
+ [].tap do |args|
48
+ args << "--debug" if debug
49
+ args << ["--kube-apiserver", kube_apiserver] if kube_apiserver
50
+ args << ["--kube-as-group", kube_as_group ] if kube_as_group
51
+ args << ["--kube-context", kube_context] if kube_context
52
+ args << ["--kube-token", kube_token] if kube_token
53
+ args << ["--kubeconfig", kubeconfig ] if kubeconfig
54
+ args << ["--namespace", namespace] if namespace
55
+ args << ["--registry-config", registry_config] if registry_config
56
+ args << ["--repository-cache", repository_cache] if repository_cache
57
+ args << ["--repository-config", repository_config] if repository_config
58
+ end.flatten
59
+ end
60
+
61
+ def args
62
+ [subcommand_name, cli_args].flatten
63
+ end
64
+
65
+ def full_cli_call
66
+ [@client.program, args].flatten.map(&:to_s)
67
+ end
68
+
69
+ def report_failure(lines, status, and_raise: true)
70
+ preamble = "#{full_cli_call} failed with exit status #{status}. Output follows:"
71
+ if @client.logger
72
+ client.logger.error(preamble)
73
+ client.logger.error(lines)
74
+ else
75
+ STDERR.puts premable
76
+ STDERR.puts lines
77
+ end
78
+ raise(Error, "#{full_cli_call} failed with exit_status #{status}") if and_raise
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,49 @@
1
+ require_relative "base"
2
+
3
+ module Rhelm
4
+ module Subcommand
5
+ ## Helm dependency subcommand: `helm dependency COMMAND CHART [flags]`.
6
+ ## docs: https://helm.sh/docs/helm/helm_dependency/
7
+ class Dependency < Base
8
+ attr_reader :chart,
9
+ :command,
10
+ :help,
11
+ :keyring,
12
+ :skip_refresh,
13
+ :verify
14
+
15
+ COMMANDS = %w(update)
16
+
17
+ def initialize(command, chart, options = {})
18
+ super(options)
19
+
20
+ @command = command.to_s
21
+ unless COMMANDS.include?(command)
22
+ raise(OptionError, "Invalid command #{command}. Valid values are: #{COMMANDS.join(', ')}")
23
+ end
24
+
25
+ @chart = chart
26
+ @help = !!options[:help]
27
+ @keyring = options[:keyring]
28
+ @skip_refresh = !!options[:skip_refresh]
29
+ @verify = !!options[:verify]
30
+ end
31
+
32
+ def subcommand_name
33
+ "dependency"
34
+ end
35
+
36
+ def cli_args
37
+ super.tap do |args|
38
+ args << '--help' if help
39
+ args << ['--keyring', keyring] if keyring
40
+ args << '--skip-refresh' if skip_refresh
41
+ args << '--verify' if verify
42
+
43
+ args << command
44
+ args << chart
45
+ end.flatten
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,27 @@
1
+ require_relative "base"
2
+
3
+ module Rhelm
4
+ module Subcommand
5
+ ## Helm env subcommand: `helm env [flags]`.
6
+ ## docs: https://helm.sh/docs/helm/helm_env/
7
+ class Env < Base
8
+ attr_reader :help
9
+
10
+ def initialize(options = {})
11
+ super
12
+
13
+ @help = options[:help]
14
+ end
15
+
16
+ def subcommand_name
17
+ "env"
18
+ end
19
+
20
+ def cli_args
21
+ super.tap do |args|
22
+ args << "--help" if help
23
+ end.flatten
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ require_relative "base"
2
+
3
+ module Rhelm
4
+ module Subcommand
5
+ ## Helm history subcommand: `helm history RELEASE_NAME [flags]`.
6
+ ## docs: https://helm.sh/docs/helm/helm_history/
7
+ class History < Base
8
+ attr_reader :release_name,
9
+ :help,
10
+ :max,
11
+ :output
12
+
13
+ def initialize(release_name, options = {})
14
+ super(options)
15
+
16
+ @release_name = release_name
17
+ @help = options[:help]
18
+ @max = options[:max]
19
+ @output = options[:output]
20
+ end
21
+
22
+ def subcommand_name
23
+ "history"
24
+ end
25
+
26
+ def cli_args
27
+ super.tap do |args|
28
+ args << "--help" if help
29
+ args << [ '--max', max ] if max
30
+ args << [ '--output', output ] if output
31
+
32
+ args << release_name
33
+ end.flatten
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,158 @@
1
+ require_relative "base"
2
+
3
+ module Rhelm
4
+ module Subcommand
5
+ ## Helm install subcommand: `helm install [NAME] [CHART] [flags]`.
6
+ ## docs: https://helm.sh/docs/helm/helm_install/
7
+ class Install < Base
8
+ attr_reader :chart,
9
+ :atomic,
10
+ :ca_file,
11
+ :cert_file,
12
+ :create_namespace,
13
+ :dependency_update,
14
+ :description,
15
+ :devel,
16
+ :disable_openapi_validation,
17
+ :dry_run,
18
+ :generate_name,
19
+ :insecure_skip_tls_verify,
20
+ :key_file,
21
+ :keyring,
22
+ :name_template,
23
+ :no_hooks,
24
+ :output,
25
+ :password,
26
+ :post_renderer,
27
+ :release,
28
+ :render_subchart_notes,
29
+ :replace,
30
+ :repo,
31
+ :set,
32
+ :set_file,
33
+ :set_string,
34
+ :skip_crds,
35
+ :timeout,
36
+ :username,
37
+ :values,
38
+ :verify,
39
+ :version,
40
+ :wait
41
+
42
+ def initialize(release, chart, options = {})
43
+ super(options)
44
+
45
+ @release = release
46
+ @chart = chart
47
+ @atomic = options[:atomic]
48
+ @ca_file = options[:ca_file]
49
+ @cert_file = options[:cert_file]
50
+ @create_namespace = options[:create_namespace]
51
+ @dependency_update = options[:dependency_update]
52
+ @description = options[:description]
53
+ @devel = !!options[:devel]
54
+ @disable_openapi_validation = !!options[:disable_openapi_validation]
55
+ @dry_run = options[:dry_run]
56
+ @generate_name = options[:generate_name]
57
+ @insecure_skip_tls_verify = options[:insecure_skip_tls_verify]
58
+ @key_file = options[:key_file]
59
+ @keyring = options[:keyring]
60
+ @name_template = options[:name_template]
61
+ @no_hooks = options[:no_hooks]
62
+ @output = options[:output]
63
+ @password = options[:password]
64
+ @post_renderer = options[:post_renderer]
65
+ @render_subchart_notes = options[:render_subchart_notes]
66
+ @replace = options[:replace]
67
+ @repo = options[:repo]
68
+ @set = options[:set]
69
+ @set_file = options[:set_file]
70
+ @set_string = options[:set_string]
71
+ @skip_crds = options[:skip_crds]
72
+ @timeout = options[:timeout]
73
+ @username = options[:username]
74
+ @values = options[:values]
75
+ @verify = options[:verify]
76
+ @version = options[:version]
77
+ @wait = options[:wait]
78
+ end
79
+
80
+ def subcommand_name
81
+ "install"
82
+ end
83
+
84
+ def cli_args
85
+ super.tap do |args|
86
+ args << '--atomic' if atomic
87
+ args << ['--ca-file', ca_file] if ca_file
88
+ args << ['--cert-file', cert_file] if cert_file
89
+ args << '--create-namespace' if create_namespace
90
+ args << '--dependency-update' if dependency_update
91
+ args << ['--description', description] if description
92
+ args << '--devel' if devel
93
+ args << '--disable-openapi-validation' if disable_openapi_validation
94
+ args << '--dry-run' if dry_run
95
+ args << '--generate-name' if generate_name
96
+ args << '--insecure-skip-tls-verify' if insecure_skip_tls_verify
97
+ args << ['--key-file', key_file] if key_file
98
+ args << ['--keyring', keyring] if keyring
99
+ args << ['--name-template', name_template] if name_template
100
+ args << '--no-hooks' if no_hooks
101
+ args << ['--output', output] if output
102
+ args << ['--password', password] if password
103
+ args << ['--post-renderer', post_renderer] if post_renderer
104
+ args << '--render-subchart-notes' if render_subchart_notes
105
+ args << '--replace' if replace
106
+ args << ['--repo', repo] if repo
107
+
108
+ if set && !set.empty?
109
+ case set
110
+ when Hash
111
+ args << set.map { |key, value| ['--set', "#{key}=#{value}" ] }.flatten
112
+ else
113
+ args << ['--set', set]
114
+ end
115
+ end
116
+
117
+ if set_file && !set_file.empty?
118
+ case set_file
119
+ when Hash
120
+ args << set_file.map { |key, value| ['--set-file', "#{key}=#{value}" ] }.flatten
121
+ else
122
+ args << ['--set-file', set_file]
123
+ end
124
+ end
125
+
126
+ if set_string && !set_string.empty?
127
+ case set_string
128
+ when Hash
129
+ args << set_string.map { |key, value| ['--set-string', "#{key}=#{value}" ] }.flatten
130
+ else
131
+ args << ['--set-string', set_string]
132
+ end
133
+ end
134
+
135
+ args << '--skip-crds' if skip_crds
136
+ args << ['--timeout', timeout] if timeout
137
+ args << ['--username', username] if username
138
+
139
+ if values && !values.empty?
140
+ case values
141
+ when Array
142
+ args << values.map { |values_file| ['--values', values_file ] }.flatten
143
+ else
144
+ args << ['--values', values]
145
+ end
146
+ end
147
+
148
+ args << '--verify' if verify
149
+ args << ['version', version] if version
150
+ args << '--wait' if wait
151
+
152
+ args << release
153
+ args << chart
154
+ end.flatten
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,71 @@
1
+ require_relative "base"
2
+
3
+ module Rhelm
4
+ module Subcommand
5
+ ## Helm install subcommand: `helm pull [NAME] [CHART] [flags]`.
6
+ ## docs: https://helm.sh/docs/helm/helm_pull/
7
+ class Pull < Base
8
+ attr_reader :ca_file,
9
+ :chart,
10
+ :cert_file,
11
+ :destination,
12
+ :devel,
13
+ :insecure_skip_tls_verify,
14
+ :key_file,
15
+ :keyring,
16
+ :password,
17
+ :prov,
18
+ :repo,
19
+ :untar,
20
+ :untardir,
21
+ :username,
22
+ :verify,
23
+ :version
24
+
25
+ def initialize(chart, options = {})
26
+ super(options)
27
+
28
+ @chart = chart
29
+ @ca_file = options[:ca_file]
30
+ @cert_file = options[:cert_file]
31
+ @destination = options[:destination]
32
+ @devel = !!options[:devel]
33
+ @insecure_skip_tls_verify = !!options[:insecure_skip_tls_verify]
34
+ @key_file = options[:key_file]
35
+ @keyring = options[:keyring]
36
+ @password = options[:password]
37
+ @repo = options[:repo]
38
+ @untar = !!options[:untar]
39
+ @untardir = options[:untardir]
40
+ @username = options[:username]
41
+ @verify = !!options[:verify]
42
+ @version = options[:version]
43
+ end
44
+
45
+ def subcommand_name
46
+ "pull"
47
+ end
48
+
49
+ def cli_args
50
+ super.tap do |args|
51
+ args << ['--ca-file', ca_file] if ca_file
52
+ args << ['--cert-file', cert_file] if cert_file
53
+ args << ['--destination', destination] if destination
54
+ args << '--devel' if devel
55
+ args << '--insecure-skip-tls-verify' if insecure_skip_tls_verify
56
+ args << ['--key-file', key_file] if key_file
57
+ args << ['--keyring', keyring] if keyring
58
+ args << ['--password', password] if password
59
+ args << ['--repo', repo] if repo
60
+ args << '--untar' if untar
61
+ args << ['--untardir', untardir] if untardir
62
+ args << ['--username', username] if username
63
+ args << '--verify' if verify
64
+ args << ['--version', version] if version
65
+
66
+ args << chart
67
+ end.flatten
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,58 @@
1
+ require_relative "base"
2
+
3
+ module Rhelm
4
+ module Subcommand
5
+ ## Helm rollback subcommand: `helm rollback <RELEASE> [REVISION] [flags]`.
6
+ ## docs: https://helm.sh/docs/helm/helm_rollback/
7
+ class Rollback < Base
8
+ attr_reader :release,
9
+ :revision,
10
+ :cleanup_on_fail,
11
+ :dry_run,
12
+ :force,
13
+ :help,
14
+ :history_max_int,
15
+ :no_hooks,
16
+ :recreate_pods,
17
+ :timeout_duration,
18
+ :wait
19
+
20
+ def initialize(release, revision, options = {})
21
+ super(options)
22
+
23
+ @release = release
24
+ @revision = revision
25
+ @cleanup_on_fail = options[:cleanup_on_fail]
26
+ @dry_run = options[:dry_run]
27
+ @force = options[:force]
28
+ @help = options[:help]
29
+ @history_max_int = options[:history_max_int]
30
+ @no_hooks = options[:no_hooks]
31
+ @recreate_pods = options[:recreate_pods]
32
+ @timeout_duration = options[:timeout_duration]
33
+ @wait = options[:wait]
34
+ end
35
+
36
+ def subcommand_name
37
+ "rollback"
38
+ end
39
+
40
+ def cli_args
41
+ super.tap do |args|
42
+ args << '--cleanup-on-fail' if cleanup_on_fail
43
+ args << '--dry-run' if dry_run
44
+ args << '--force' if force
45
+ args << '--help' if help
46
+ args << ['--history-max-int', history_max_int] if history_max_int
47
+ args << '--no-hooks' if no_hooks
48
+ args << '--recreate-pods' if recreate_pods
49
+ args << ['--timeout-duration', timeout_duration] if timeout_duration
50
+ args << '--wait' if wait
51
+
52
+ args << release
53
+ args << revision
54
+ end.flatten
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,43 @@
1
+ require_relative "base"
2
+
3
+ module Rhelm
4
+ module Subcommand
5
+ ## Helm status subcommand: `helm status RELEASE_NAME [flags]`.
6
+ ## docs: https://helm.sh/docs/helm/helm_status/
7
+ class Status < Base
8
+ attr_reader :release_name,
9
+ :help
10
+
11
+ def initialize(release_name, options = {})
12
+ super(options)
13
+
14
+ @release_name = release_name
15
+ @help = options[:help]
16
+ end
17
+
18
+ def subcommand_name
19
+ "status"
20
+ end
21
+
22
+ def exists?
23
+ run(raise_on_error: false) do |lines,status|
24
+ if status == 0
25
+ true
26
+ elsif status == 1 && /Error: release: not found/m.match(lines)
27
+ false
28
+ else
29
+ report_failure(lines, status)
30
+ end
31
+ end
32
+ end
33
+
34
+ def cli_args
35
+ super.tap do |args|
36
+ args << '--help' if help
37
+
38
+ args << release_name
39
+ end.flatten
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,37 @@
1
+ require_relative "base"
2
+
3
+ module Rhelm
4
+ module Subcommand
5
+ ## Helm test subcommand: `helm test [RELEASE] [flags]`.
6
+ ## docs: https://helm.sh/docs/helm/helm_test/
7
+ class Test < Base
8
+ attr_reader :release,
9
+ :help,
10
+ :logs,
11
+ :timeout
12
+
13
+ def initialize(release, options = {})
14
+ super(options)
15
+
16
+ @release = options[:release]
17
+ @help = options[:help]
18
+ @logs = options[:logs]
19
+ @timeout = options[:timeout]
20
+ end
21
+
22
+ def subcommand_name
23
+ "test"
24
+ end
25
+
26
+ def cli_args
27
+ super.tap do |args|
28
+ args << '--help' if help
29
+ args << '--logs' if logs
30
+ args << ['--timeout', timeout] if timeout
31
+
32
+ args << release
33
+ end.flatten
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,27 @@
1
+ require_relative "base"
2
+
3
+ module Rhelm
4
+ module Subcommand
5
+ ## Helm uninstall subcommand: `helm uninstall RELEASE_NAME [...] [flags]`.
6
+ ## docs: https://helm.sh/docs/helm/helm_uninstall/
7
+ class Uninstall < Base
8
+ attr_reader :release_name
9
+
10
+ def initialize(release_name, options = {})
11
+ super(options)
12
+
13
+ @release_name = release_name
14
+ end
15
+
16
+ def subcommand_name
17
+ "uninstall"
18
+ end
19
+
20
+ def cli_args
21
+ super.tap do |args|
22
+ args << release_name
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,169 @@
1
+ require_relative "base"
2
+
3
+ module Rhelm
4
+ module Subcommand
5
+ ## Helm upgrade subcommand: `helm upgrade [RELEASE] [CHART] [flags]`.
6
+ ## docs: https://helm.sh/docs/helm/helm_upgrade/
7
+ class Upgrade < Base
8
+ attr_reader :release,
9
+ :chart,
10
+ :atomic,
11
+ :ca_file,
12
+ :cert_file,
13
+ :cleanup_on_fail,
14
+ :create_namespace,
15
+ :dependency_update,
16
+ :description,
17
+ :devel,
18
+ :disable_openapi_validation,
19
+ :dry_run,
20
+ :force,
21
+ :help,
22
+ :history_max,
23
+ :insecure_skip_tls_verify,
24
+ :install,
25
+ :key_file,
26
+ :keyring,
27
+ :no_hooks,
28
+ :output,
29
+ :password,
30
+ :post_renderer,
31
+ :render_subchart_notes,
32
+ :repo,
33
+ :reset_values,
34
+ :reuse_values,
35
+ :set,
36
+ :set_file,
37
+ :set_string,
38
+ :skip_crds,
39
+ :timeout,
40
+ :username,
41
+ :values,
42
+ :verify,
43
+ :version,
44
+ :wait
45
+
46
+
47
+ def initialize(release, chart, options = {})
48
+ super(options)
49
+
50
+ @release = release
51
+ @chart = chart
52
+ @atomic = !!options[:atomic]
53
+ @ca_file = options[:ca_file]
54
+ @cert_file = options[:cert_file]
55
+ @cleanup_on_fail = !!options[:cleanup_on_fail]
56
+ @dependency_update = !!options[:dependency_update]
57
+ @description = options[:description]
58
+ @devel = !!options[:devel]
59
+ @disable_openapi_validation = !!options[:disable_openapi_validation]
60
+ @dry_run = !!options[:dry_run]
61
+ @force = !!options[:force]
62
+ @help = !!options[:help]
63
+ @history_max = options[:history_max]
64
+ @insecure_skip_tls_verify = !!options[:insecure_skip_tls_verify]
65
+ @install = !!options[:install]
66
+ @key_file = options[:key_file]
67
+ @keyring = options[:keyring]
68
+ @no_hooks = !!options[:no_hooks]
69
+ @output = options[:output]
70
+ @password = options[:password]
71
+ @post_renderer = options[:post_renderer]
72
+ @render_subchart_notes = !!options[:render_subchart_notes]
73
+ @repo = options[:repo]
74
+ @reset_values = !!options[:reset_values]
75
+ @reuse_values = !!options[:reuse_values]
76
+ @set = options[:set]
77
+ @set_file = options[:set_file]
78
+ @set_string = options[:set_string]
79
+ @skip_crds = !!options[:skip_crds]
80
+ @timeout = options[:timeout]
81
+ @username = options[:username]
82
+ @values = options[:values]
83
+ @verify = !!options[:verify]
84
+ @version = options[:version]
85
+ @wait = !!options[:wait]
86
+ end
87
+
88
+ def subcommand_name
89
+ "upgrade"
90
+ end
91
+
92
+ def cli_args
93
+ super.tap do |args|
94
+ args << '--atomic' if atomic
95
+ args << ['--ca-file', ca_file] if ca_file
96
+ args << ['--cert-file', cert_file] if cert_file
97
+ args << '--cleanup-on-fail' if cleanup_on_fail
98
+ args << '--dependency-update' if dependency_update
99
+ args << ['--description', description] if description
100
+ args << '--devel' if devel
101
+ args << '--disable-openapi-validation' if disable_openapi_validation
102
+ args << '--dry-run' if dry_run
103
+ args << '--force' if force
104
+ args << '--help' if help
105
+ args << ['--history-max', history_max] if history_max
106
+ args << '--insecure-skip-tls-verify' if insecure_skip_tls_verify
107
+ args << '--install' if install
108
+ args << ['--key-file', key_file] if key_file
109
+ args << ['--keyring', keyring] if keyring
110
+ args << '--no-hooks' if no_hooks
111
+ args << ['--output', output] if output
112
+ args << ['--password', password] if password
113
+ args << ['--post-renderer', post_renderer] if post_renderer
114
+ args << '--render-subchart-notes' if render_subchart_notes
115
+ args << ['--repo', repo] if repo
116
+ args << '--reset-values' if reset_values
117
+ args << '--reuse-values' if reuse_values
118
+
119
+ if set && !set.empty?
120
+ case set
121
+ when Hash
122
+ args << set.map { |key, value| ['--set', "#{key}=#{value}" ] }.flatten
123
+ else
124
+ args << ['--set', set]
125
+ end
126
+ end
127
+
128
+ if set_file && !set_file.empty?
129
+ case set_file
130
+ when Hash
131
+ args << set_file.map { |key, value| ['--set-file', "#{key}=#{value}" ] }.flatten
132
+ else
133
+ args << ['--set-file', set_file]
134
+ end
135
+ end
136
+
137
+ if set_string && !set_string.empty?
138
+ case set_string
139
+ when Hash
140
+ args << set_string.map { |key, value| ['--set-string', "#{key}=#{value}" ] }.flatten
141
+ else
142
+ args << ['--set-string', set_string]
143
+ end
144
+ end
145
+
146
+ args << '--skip-crds' if skip_crds
147
+ args << ['--timeout', timeout] if timeout
148
+ args << ['--username', username] if username
149
+
150
+ if values && !values.empty?
151
+ case values
152
+ when Array
153
+ args << values.map { |values_file| ['--values', values_file ] }.flatten
154
+ else
155
+ args << ['--values', values]
156
+ end
157
+ end
158
+
159
+ args << '--verify' if verify
160
+ args << ['version', version] if version
161
+ args << '--wait' if wait
162
+
163
+ args << release
164
+ args << chart
165
+ end.flatten
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,31 @@
1
+ require_relative "base"
2
+
3
+ module Rhelm
4
+ module Subcommand
5
+ ## Helm verify subcommand: `helm verify PATH [flags]`.
6
+ ## docs: https://helm.sh/docs/helm/helm_verify/
7
+ class Verify < Base
8
+ attr_reader :path,
9
+ :keyring
10
+
11
+ def initialize(path, options = {})
12
+ super(options)
13
+
14
+ @path = path
15
+ @keyring = options[:keyring]
16
+ end
17
+
18
+ def subcommand_name
19
+ "verify"
20
+ end
21
+
22
+ def cli_args
23
+ super.tap do |args|
24
+ args << ['--keyring', keyring] if keyring
25
+
26
+ args << path
27
+ end.flatten
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ require_relative "base"
2
+
3
+ module Rhelm
4
+ module Subcommand
5
+ ## Helm version subcommand: `helm version [flags]`.
6
+ ## docs: https://helm.sh/docs/helm/helm_version/
7
+ class Version < Base
8
+ attr_reader :help,
9
+ :short,
10
+ :template
11
+
12
+ def initialize(options = {})
13
+ super
14
+
15
+ @help = options[:help]
16
+ @short = options[:short]
17
+ @template = options[:template]
18
+ end
19
+
20
+ def subcommand_name
21
+ "version"
22
+ end
23
+
24
+ def cli_args
25
+ super.tap do |args|
26
+ args << '--help' if help
27
+ args << '--short' if short
28
+ args << ['--template', template] if template
29
+ end.flatten
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ require 'open3'
2
+ require 'pry-byebug'
3
+
4
+ module Rhelm
5
+ class Client
6
+ class SubcommandProxy
7
+ def initialize(subcommand_name, client, *args, **kwargs)
8
+ unless SUBCOMMANDS.include?(subcommand_name.to_sym)
9
+ raise(Error, "Unknown subcommand #{subcommand_name}")
10
+ end
11
+
12
+ kwargs[:client] ||= client
13
+ class_name = "::Rhelm::Subcommand::#{subcommand_name.to_s.capitalize}"
14
+ @subcommand = Object.const_get(class_name).new(*args, **kwargs)
15
+ end
16
+
17
+ def method_missing(m, *args, **kwargs, &block)
18
+ @subcommand.send m, *args, **kwargs, &block
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,4 @@
1
+
2
+ module Rhelm
3
+ VERSION = "0.1.0-alpha1"
4
+ end
data/rhelm.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ require_relative 'lib/rhelm/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "rhelm"
5
+ spec.version = Rhelm::VERSION
6
+ spec.authors = ["Jack Newton", "Nick Marden"]
7
+ spec.email = ["jnewton@avvo.com", "nick@rrsoft.co"]
8
+ spec.licenses = ["MIT"]
9
+
10
+ spec.summary = "A wrapper around helm3, including error detection and output parsing callback support"
11
+ spec.description = "Invoke Helm 3.x commands from Ruby with easy result handling"
12
+ spec.homepage = "https://github.com/avvo/ruby-helm"
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.1")
14
+
15
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = spec.homepage
19
+ #spec.metadata["changelog_uri"] = ""
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rhelm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.pre.alpha1
5
+ platform: ruby
6
+ authors:
7
+ - Jack Newton
8
+ - Nick Marden
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2021-05-23 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Invoke Helm 3.x commands from Ruby with easy result handling
15
+ email:
16
+ - jnewton@avvo.com
17
+ - nick@rrsoft.co
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - ".gitignore"
23
+ - Gemfile
24
+ - LICENSE.txt
25
+ - README.md
26
+ - Rakefile
27
+ - bin/console
28
+ - bin/setup
29
+ - lib/rhelm.rb
30
+ - lib/rhelm/client.rb
31
+ - lib/rhelm/client/simple_logger.rb
32
+ - lib/rhelm/subcommand/base.rb
33
+ - lib/rhelm/subcommand/dependency.rb
34
+ - lib/rhelm/subcommand/env.rb
35
+ - lib/rhelm/subcommand/history.rb
36
+ - lib/rhelm/subcommand/install.rb
37
+ - lib/rhelm/subcommand/pull.rb
38
+ - lib/rhelm/subcommand/rollback.rb
39
+ - lib/rhelm/subcommand/status.rb
40
+ - lib/rhelm/subcommand/test.rb
41
+ - lib/rhelm/subcommand/uninstall.rb
42
+ - lib/rhelm/subcommand/upgrade.rb
43
+ - lib/rhelm/subcommand/verify.rb
44
+ - lib/rhelm/subcommand/version.rb
45
+ - lib/rhelm/subcommand_proxy.rb
46
+ - lib/rhelm/version.rb
47
+ - rhelm.gemspec
48
+ homepage: https://github.com/avvo/ruby-helm
49
+ licenses:
50
+ - MIT
51
+ metadata:
52
+ allowed_push_host: https://rubygems.org
53
+ homepage_uri: https://github.com/avvo/ruby-helm
54
+ source_code_uri: https://github.com/avvo/ruby-helm
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 2.7.1
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.3.1
69
+ requirements: []
70
+ rubygems_version: 3.1.2
71
+ signing_key:
72
+ specification_version: 4
73
+ summary: A wrapper around helm3, including error detection and output parsing callback
74
+ support
75
+ test_files: []