helm-wrapper 0.1.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 +7 -0
- data/.gitignore +28 -0
- data/.gitlab-ci.yml +37 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +21 -0
- data/Rakefile +13 -0
- data/bin/console +16 -0
- data/bin/setup +18 -0
- data/helm-wrapper.gemspec +38 -0
- data/lib/helm-wrapper.rb +59 -0
- data/lib/helm-wrapper/common.rb +27 -0
- data/lib/helm-wrapper/shared.rb +16 -0
- data/lib/helm-wrapper/shared/auths.rb +9 -0
- data/lib/helm-wrapper/shared/auths/azure.rb +176 -0
- data/lib/helm-wrapper/shared/auths/common.rb +91 -0
- data/lib/helm-wrapper/shared/binary.rb +113 -0
- data/lib/helm-wrapper/shared/chart.rb +120 -0
- data/lib/helm-wrapper/shared/config.rb +145 -0
- data/lib/helm-wrapper/shared/latest.rb +79 -0
- data/lib/helm-wrapper/shared/logger.rb +80 -0
- data/lib/helm-wrapper/shared/logging.rb +77 -0
- data/lib/helm-wrapper/shared/runner.rb +250 -0
- data/lib/helm-wrapper/shared/variables.rb +66 -0
- data/lib/helm-wrapper/tasks.rb +11 -0
- data/lib/helm-wrapper/tasks/apply.rb +72 -0
- data/lib/helm-wrapper/tasks/binary.rb +195 -0
- data/lib/helm-wrapper/tasks/destroy.rb +70 -0
- data/lib/helm-wrapper/version.rb +13 -0
- metadata +87 -0
@@ -0,0 +1,91 @@
|
|
1
|
+
###############################################################################
|
2
|
+
|
3
|
+
module HelmWrapper
|
4
|
+
|
5
|
+
###############################################################################
|
6
|
+
|
7
|
+
module Shared
|
8
|
+
|
9
|
+
###############################################################################
|
10
|
+
|
11
|
+
module Auths
|
12
|
+
|
13
|
+
###############################################################################
|
14
|
+
|
15
|
+
class Common
|
16
|
+
|
17
|
+
###############################################################################
|
18
|
+
|
19
|
+
include HelmWrapper::Shared::Logging
|
20
|
+
|
21
|
+
###############################################################################
|
22
|
+
|
23
|
+
@@type
|
24
|
+
|
25
|
+
###############################################################################
|
26
|
+
|
27
|
+
@options
|
28
|
+
@variables
|
29
|
+
|
30
|
+
###############################################################################
|
31
|
+
|
32
|
+
def initialize(code:, config:, options:, service:, variables:)
|
33
|
+
logger.fatal("This class should not be used directly! Please create an authenticator-specific class instead!")
|
34
|
+
end
|
35
|
+
|
36
|
+
###############################################################################
|
37
|
+
|
38
|
+
def auth()
|
39
|
+
logger.fatal("The authenticator specific class should override the 'auth' method to complete the authentication process!")
|
40
|
+
end
|
41
|
+
|
42
|
+
###############################################################################
|
43
|
+
|
44
|
+
def clear()
|
45
|
+
logger.fatal("The authenticator specific class should override the 'auth' method to clear any authentication details!")
|
46
|
+
end
|
47
|
+
|
48
|
+
###############################################################################
|
49
|
+
|
50
|
+
def type()
|
51
|
+
logger.fatal("The authenticator specific class should set the 'type' class variable to a string!") unless @@type.kind_of?(String)
|
52
|
+
|
53
|
+
return @@type
|
54
|
+
end
|
55
|
+
|
56
|
+
###############################################################################
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
###############################################################################
|
61
|
+
|
62
|
+
def construct(options:, variables:)
|
63
|
+
@options = options
|
64
|
+
@variables = variables
|
65
|
+
|
66
|
+
specific
|
67
|
+
end
|
68
|
+
|
69
|
+
###############################################################################
|
70
|
+
|
71
|
+
def specific()
|
72
|
+
logger.fatal("The authenticator specific class should override the 'specific' method to include authenticator specific validation and setup, or simply return 'true' if it is not required.")
|
73
|
+
end
|
74
|
+
|
75
|
+
###############################################################################
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
###############################################################################
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
###############################################################################
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
###############################################################################
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
###############################################################################
|
@@ -0,0 +1,113 @@
|
|
1
|
+
###############################################################################
|
2
|
+
|
3
|
+
module HelmWrapper
|
4
|
+
|
5
|
+
###############################################################################
|
6
|
+
|
7
|
+
module Shared
|
8
|
+
|
9
|
+
###############################################################################
|
10
|
+
|
11
|
+
class Binary
|
12
|
+
|
13
|
+
###############################################################################
|
14
|
+
|
15
|
+
include HelmWrapper::Shared::Logging
|
16
|
+
|
17
|
+
###############################################################################
|
18
|
+
|
19
|
+
attr_accessor :name
|
20
|
+
|
21
|
+
###############################################################################
|
22
|
+
|
23
|
+
attr_reader :base
|
24
|
+
attr_reader :directory
|
25
|
+
attr_reader :platform
|
26
|
+
attr_reader :version
|
27
|
+
|
28
|
+
###############################################################################
|
29
|
+
|
30
|
+
def initialize(options:)
|
31
|
+
logger.fatal("Binary base path must be a string!") unless options["base"].kind_of?(String)
|
32
|
+
logger.fatal("Binary base path must not be blank!") if options["base"].strip.empty?
|
33
|
+
|
34
|
+
@base = options["base"]
|
35
|
+
|
36
|
+
logger.fatal("Binary version must be a string!") unless options["version"].kind_of?(String)
|
37
|
+
logger.fatal("Binary version must not be blank!") if options["version"].strip.empty?
|
38
|
+
|
39
|
+
@version = options["version"]
|
40
|
+
|
41
|
+
@platform = platform_detect
|
42
|
+
|
43
|
+
@directory = File.join(@base, @version, @platform)
|
44
|
+
@name = "helm"
|
45
|
+
end
|
46
|
+
|
47
|
+
###############################################################################
|
48
|
+
|
49
|
+
def check()
|
50
|
+
result = false
|
51
|
+
|
52
|
+
if exists and executable then
|
53
|
+
result = system("\"#{path}\" version --short") || false
|
54
|
+
end
|
55
|
+
|
56
|
+
return result
|
57
|
+
end
|
58
|
+
|
59
|
+
###############################################################################
|
60
|
+
|
61
|
+
def exists()
|
62
|
+
return File.exist?(path)
|
63
|
+
end
|
64
|
+
|
65
|
+
###############################################################################
|
66
|
+
|
67
|
+
def executable()
|
68
|
+
return File.executable?(path)
|
69
|
+
end
|
70
|
+
|
71
|
+
###############################################################################
|
72
|
+
|
73
|
+
def path()
|
74
|
+
return File.join(@directory, @name)
|
75
|
+
end
|
76
|
+
|
77
|
+
###############################################################################
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
###############################################################################
|
82
|
+
|
83
|
+
def platform_detect
|
84
|
+
return "darwin" if platform_is_mac
|
85
|
+
return "linux" if platform_is_linux
|
86
|
+
logger.fatal("Platform is NOT supported: #{RUBY_PLATFORM}")
|
87
|
+
end
|
88
|
+
|
89
|
+
###############################################################################
|
90
|
+
|
91
|
+
def platform_is_mac
|
92
|
+
RUBY_PLATFORM =~ /darwin/
|
93
|
+
end
|
94
|
+
|
95
|
+
###############################################################################
|
96
|
+
|
97
|
+
def platform_is_linux
|
98
|
+
RUBY_PLATFORM =~ /linux/
|
99
|
+
end
|
100
|
+
|
101
|
+
###############################################################################
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
###############################################################################
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
###############################################################################
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
###############################################################################
|
@@ -0,0 +1,120 @@
|
|
1
|
+
###############################################################################
|
2
|
+
|
3
|
+
module HelmWrapper
|
4
|
+
|
5
|
+
###############################################################################
|
6
|
+
|
7
|
+
module Shared
|
8
|
+
|
9
|
+
###############################################################################
|
10
|
+
|
11
|
+
class Chart
|
12
|
+
|
13
|
+
###############################################################################
|
14
|
+
|
15
|
+
include HelmWrapper::Shared::Logging
|
16
|
+
|
17
|
+
###############################################################################
|
18
|
+
|
19
|
+
attr_reader :oci
|
20
|
+
attr_reader :name
|
21
|
+
attr_reader :artefact
|
22
|
+
|
23
|
+
###############################################################################
|
24
|
+
|
25
|
+
def initialize(options:)
|
26
|
+
logger.fatal("Chart name must be a string!") unless options["name"].kind_of?(String)
|
27
|
+
logger.fatal("Chart name must not be blank!") if options["name"].strip.empty?
|
28
|
+
|
29
|
+
@name = options["name"]
|
30
|
+
|
31
|
+
logger.fatal("Chart repos must be a list of hashes!") unless options["repos"].kind_of?(Array)
|
32
|
+
|
33
|
+
repos = options["repos"]
|
34
|
+
|
35
|
+
@oci = Array.new
|
36
|
+
@artefact = Array.new
|
37
|
+
|
38
|
+
repos.each do |repo|
|
39
|
+
logger.fatal("All elements of chart repos must be hashes!") unless repo.kind_of?(Hash)
|
40
|
+
|
41
|
+
logger.fatal("Chart repo: #{hash["name"]} must have a type attribute!") unless repo.key?("type")
|
42
|
+
logger.fatal("Chart repo: #{hash["name"]} type must be a string!") unless repo["type"].kind_of?(String)
|
43
|
+
logger.fatal("Chart repo: #{hash["name"]} type must either be 'artefact' or 'oci'.") unless [ "artefact", "oci" ].include?(repo["type"])
|
44
|
+
|
45
|
+
is_artefact = repo["type"] == "artefact" ? true : false
|
46
|
+
is_oci = repo["type"] == "oci" ? true : false
|
47
|
+
|
48
|
+
hash = Hash.new
|
49
|
+
|
50
|
+
logger.fatal("Chart repos must have a name attribute!") unless repo.key?("name")
|
51
|
+
logger.fatal("Chart repo name must be a string!") unless repo["name"].kind_of?(String)
|
52
|
+
logger.fatal("Chart repo name must not be blank!") if repo["name"].strip.empty?
|
53
|
+
|
54
|
+
hash["name"] = repo["name"].strip
|
55
|
+
|
56
|
+
logger.fatal("Chart repo: #{hash["name"]} must have a url attribute!") unless repo.key?("url")
|
57
|
+
logger.fatal("Chart repo: #{hash["name"]} url must be a string!") unless repo["url"].kind_of?(String)
|
58
|
+
logger.fatal("Chart repo: #{hash["name"]} url must not be blank!") if repo["url"].strip.empty?
|
59
|
+
|
60
|
+
hash["url"] = repo["url"].strip
|
61
|
+
|
62
|
+
if repo.key?("username") then
|
63
|
+
logger.fatal("Chart repo: #{hash["name"]} username must be a string!") unless repo["username"].kind_of?(String)
|
64
|
+
logger.fatal("Chart repo: #{hash["name"]} username must not be blank!") if repo["username"].strip.empty?
|
65
|
+
|
66
|
+
repo_username = repo["username"].strip
|
67
|
+
|
68
|
+
logger.fatal("Chart repo: #{hash["name"]} username attribute must refer to a valid environment variable that holds the actual repository username!") unless ENV.key?(repo_username)
|
69
|
+
logger.fatal("Environment variable holding the username for chart repo: #{hash["name"]} is blank!") if ENV[repo_username].strip.empty?
|
70
|
+
|
71
|
+
hash["username"] = ENV[repo_username].strip
|
72
|
+
|
73
|
+
logger.fatal("Chart repo: #{hash["name"]} must have a password attribute if 'username' is set!") unless repo.key?("password")
|
74
|
+
logger.fatal("Chart repo: #{hash["name"]} password must be a string!") unless repo["password"].kind_of?(String)
|
75
|
+
logger.fatal("Chart repo: #{hash["name"]} password must not be blank!") if repo["password"].strip.empty?
|
76
|
+
|
77
|
+
repo_password = repo["password"].strip
|
78
|
+
|
79
|
+
logger.fatal("Chart repo: #{hash["name"]} password attribute must refer to a valid environment variable that holds the actual repository password!") unless ENV.key?(repo_password)
|
80
|
+
logger.fatal("Environment variable holding the password for chart repo: #{hash["name"]} is blank!") if ENV[repo_password].strip.empty?
|
81
|
+
|
82
|
+
hash["password"] = ENV[repo_password].strip
|
83
|
+
else
|
84
|
+
fatal("Chart repo: #{hash["name"]} is an OCI repository therefore must have a username attribute! Public OCI repositories do not need to be declared.") if is_oci
|
85
|
+
hash["username"] = nil
|
86
|
+
hash["password"] = nil
|
87
|
+
end
|
88
|
+
|
89
|
+
hash["active"] = false
|
90
|
+
|
91
|
+
artefact.append(hash) if is_artefact
|
92
|
+
oci.append(hash) if is_oci
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
###############################################################################
|
97
|
+
|
98
|
+
def artefact_active(active:, index:)
|
99
|
+
artefact[index]["active"] = active
|
100
|
+
end
|
101
|
+
|
102
|
+
###############################################################################
|
103
|
+
|
104
|
+
def oci_active(active:, index:)
|
105
|
+
oci[index]["active"] = active
|
106
|
+
end
|
107
|
+
|
108
|
+
###############################################################################
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
###############################################################################
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
###############################################################################
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
###############################################################################
|
@@ -0,0 +1,145 @@
|
|
1
|
+
###############################################################################
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
###############################################################################
|
6
|
+
|
7
|
+
module HelmWrapper
|
8
|
+
|
9
|
+
###############################################################################
|
10
|
+
|
11
|
+
module Shared
|
12
|
+
|
13
|
+
###############################################################################
|
14
|
+
|
15
|
+
class Config
|
16
|
+
|
17
|
+
###############################################################################
|
18
|
+
|
19
|
+
include HelmWrapper::Shared::Logging
|
20
|
+
|
21
|
+
###############################################################################
|
22
|
+
|
23
|
+
@@config_exts = [ "", ".yaml", ".yml" ]
|
24
|
+
|
25
|
+
###############################################################################
|
26
|
+
|
27
|
+
@@variable_files_name = "helmvars"
|
28
|
+
@@variable_files_exts = [ ".yaml", ".yml" ]
|
29
|
+
|
30
|
+
###############################################################################
|
31
|
+
|
32
|
+
attr_reader :auths
|
33
|
+
attr_reader :base
|
34
|
+
attr_reader :chart
|
35
|
+
attr_reader :name
|
36
|
+
attr_reader :namespace
|
37
|
+
attr_reader :path
|
38
|
+
attr_reader :release
|
39
|
+
attr_reader :variable_files
|
40
|
+
attr_reader :variables
|
41
|
+
|
42
|
+
###############################################################################
|
43
|
+
|
44
|
+
def initialize(chart:, options:)
|
45
|
+
logger.fatal("Configuration base path must be a string!") unless options["base"].kind_of?(String)
|
46
|
+
logger.fatal("Configuration base path must not be blank!") if options["base"].strip.empty?
|
47
|
+
|
48
|
+
@base = options["base"]
|
49
|
+
|
50
|
+
logger.fatal("Configuration name must be a string!") unless options["name"].kind_of?(String)
|
51
|
+
logger.fatal("Configuration name must not be blank!") if options["name"].strip.empty?
|
52
|
+
|
53
|
+
@name = options["name"]
|
54
|
+
|
55
|
+
logger.fatal("Configuration destination namespace must be a string!") unless options["namespace"].kind_of?(String)
|
56
|
+
logger.fatal("Configuration destination namespace must not be blank!") if options["namespace"].strip.empty?
|
57
|
+
|
58
|
+
namespace = options["namespace"]
|
59
|
+
|
60
|
+
logger.fatal("Configuration release name must be a string!") unless options["release"].kind_of?(String)
|
61
|
+
logger.fatal("Configuration release name must not be blank!") if options["release"].strip.empty?
|
62
|
+
|
63
|
+
release = options["release"]
|
64
|
+
|
65
|
+
logger.fatal("Configuration authenticator for Azure enabled must be a Boolean!") unless [ true, false ].include?(options["auth-azure"])
|
66
|
+
|
67
|
+
auth_azure = options["auth-azure"]
|
68
|
+
|
69
|
+
logger.fatal("Configuration authenticator for Azure options must be a Hash!") unless options["auth-azure-options"].kind_of?(Hash)
|
70
|
+
|
71
|
+
auth_azure_options = options["auth-azure-options"]
|
72
|
+
|
73
|
+
@chart = chart
|
74
|
+
@path = find(base: @base, name: @name, exts: @@config_exts, description: "Configuration")
|
75
|
+
|
76
|
+
yaml = YAML.load(File.read(@path))
|
77
|
+
logger.fatal("Invalid YAML in configuration file: #{@path}") unless yaml.kind_of?(Hash)
|
78
|
+
|
79
|
+
if yaml.key?("variables") then
|
80
|
+
logger.fatal("Key 'variables' is not a hash in configuration file: #{@path}") unless yaml["variables"].kind_of?(Hash)
|
81
|
+
@variables = HelmWrapper::Shared::Variables.new(values: yaml["variables"])
|
82
|
+
else
|
83
|
+
@variables = HelmWrapper::Shared::Variables.new()
|
84
|
+
end
|
85
|
+
|
86
|
+
@variable_files = yaml.key?("helm") ? validate(variable_files: yaml["helm"]) : Array.new
|
87
|
+
|
88
|
+
begin
|
89
|
+
namespace = namespace % @variables.values
|
90
|
+
release = release % @variables.values
|
91
|
+
rescue
|
92
|
+
logger.fatal("Provided configuration options contain variables that are not included in the configuration file!")
|
93
|
+
end
|
94
|
+
|
95
|
+
@namespace = namespace
|
96
|
+
@release = release
|
97
|
+
|
98
|
+
@auths = Array.new
|
99
|
+
@auths.append(HelmWrapper::Shared::Auths::Azure.new(options: auth_azure_options, variables: @variables)) if auth_azure
|
100
|
+
end
|
101
|
+
|
102
|
+
###############################################################################
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
###############################################################################
|
107
|
+
|
108
|
+
def find(base:, name:, exts:, description: "File")
|
109
|
+
@@config_exts.each do |config_ext|
|
110
|
+
path = File.join(base, name + config_ext)
|
111
|
+
return path if File.file?(path)
|
112
|
+
end
|
113
|
+
|
114
|
+
logger.fatal("#{description} name: #{@name} not found in location: #{@base}!")
|
115
|
+
end
|
116
|
+
|
117
|
+
###############################################################################
|
118
|
+
|
119
|
+
def validate(variable_files:)
|
120
|
+
logger.fatal("Optional key 'variable_files' must be a list of strings!") unless variable_files.kind_of?(Array)
|
121
|
+
|
122
|
+
result = Array.new
|
123
|
+
|
124
|
+
variable_files.each do |variable_file|
|
125
|
+
logger.fatal("All elements of 'helm' must be strings!") unless variable_file.kind_of?(String)
|
126
|
+
logger.fatal("All elements of 'helm' must not be blank!") if variable_file.strip.empty?
|
127
|
+
result.append(find(base: File.join(@base, @@variable_files_name), name: variable_file.strip, exts: @@variable_files_exts, description: "Helm values file"))
|
128
|
+
end
|
129
|
+
|
130
|
+
return result
|
131
|
+
end
|
132
|
+
|
133
|
+
###############################################################################
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
###############################################################################
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
###############################################################################
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
###############################################################################
|