hetzner-k3s 0.4.9 → 0.5.3
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/.rubocop.yml +121 -0
- data/Dockerfile +5 -2
- data/Gemfile +5 -3
- data/Gemfile.lock +24 -3
- data/README.md +7 -85
- data/Rakefile +5 -3
- data/bin/build.sh +3 -3
- data/bin/{console → console.sh} +3 -3
- data/bin/{setup → setup.sh} +0 -0
- data/hetzner-k3s.gemspec +25 -21
- data/lib/hetzner/infra/client.rb +17 -15
- data/lib/hetzner/infra/firewall.rb +92 -90
- data/lib/hetzner/infra/load_balancer.rb +62 -59
- data/lib/hetzner/infra/network.rb +31 -30
- data/lib/hetzner/infra/placement_group.rb +25 -21
- data/lib/hetzner/infra/server.rb +37 -31
- data/lib/hetzner/infra/ssh_key.rb +34 -35
- data/lib/hetzner/infra.rb +5 -1
- data/lib/hetzner/k3s/cli.rb +279 -262
- data/lib/hetzner/k3s/cluster.rb +448 -397
- data/lib/hetzner/k3s/version.rb +3 -1
- data/lib/hetzner/utils.rb +42 -38
- data/lib/hetzner.rb +2 -0
- metadata +26 -10
data/lib/hetzner/k3s/version.rb
CHANGED
data/lib/hetzner/utils.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
module Utils
|
|
2
|
+
CMD_FILE_PATH = '/tmp/cli.cmd'
|
|
3
|
+
|
|
2
4
|
def which(cmd)
|
|
3
5
|
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
|
4
6
|
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
|
@@ -10,90 +12,92 @@ module Utils
|
|
|
10
12
|
nil
|
|
11
13
|
end
|
|
12
14
|
|
|
13
|
-
def
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
})
|
|
15
|
+
def write_file(path, content, append: false)
|
|
16
|
+
File.open(path, append ? 'a' : 'w') { |file| file.write(content) }
|
|
17
|
+
end
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
def run(command, kubeconfig_path:)
|
|
20
|
+
env = ENV.to_hash.merge({ 'KUBECONFIG' => kubeconfig_path })
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
write_file CMD_FILE_PATH, <<-CONTENT
|
|
23
|
+
set -euo pipefail
|
|
24
|
+
#{command}
|
|
25
|
+
CONTENT
|
|
24
26
|
|
|
25
|
-
FileUtils.chmod(
|
|
27
|
+
FileUtils.chmod('+x', CMD_FILE_PATH)
|
|
26
28
|
|
|
27
29
|
begin
|
|
28
30
|
process = nil
|
|
29
31
|
|
|
30
32
|
at_exit do
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
rescue Errno::ESRCH, Interrupt
|
|
34
|
-
end
|
|
33
|
+
process&.send_signal('SIGTERM')
|
|
34
|
+
rescue Errno::ESRCH, Interrupt
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
Subprocess.check_call([
|
|
37
|
+
Subprocess.check_call(['bash', '-c', CMD_FILE_PATH], env:) do |p|
|
|
38
38
|
process = p
|
|
39
39
|
end
|
|
40
|
-
|
|
41
40
|
rescue Subprocess::NonZeroExit
|
|
42
|
-
puts
|
|
41
|
+
puts 'Command failed: non-zero exit code'
|
|
43
42
|
exit 1
|
|
44
43
|
rescue Interrupt
|
|
45
|
-
puts
|
|
44
|
+
puts 'Command interrupted'
|
|
46
45
|
exit 1
|
|
47
46
|
end
|
|
48
47
|
end
|
|
49
48
|
|
|
50
49
|
def wait_for_ssh(server)
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
retries = 0
|
|
51
|
+
|
|
52
|
+
Timeout.timeout(5) do
|
|
53
|
+
server_name = server['name']
|
|
53
54
|
|
|
54
55
|
puts "Waiting for server #{server_name} to be up..."
|
|
55
56
|
|
|
56
57
|
loop do
|
|
57
|
-
result = ssh(server,
|
|
58
|
-
break if result ==
|
|
58
|
+
result = ssh(server, 'echo UP')
|
|
59
|
+
break if result == 'UP'
|
|
59
60
|
end
|
|
60
61
|
|
|
61
62
|
puts "...server #{server_name} is now up."
|
|
62
63
|
end
|
|
63
64
|
rescue Errno::ENETUNREACH, Errno::EHOSTUNREACH, Timeout::Error, IOError
|
|
64
|
-
|
|
65
|
+
retries += 1
|
|
66
|
+
retry if retries <= 15
|
|
65
67
|
end
|
|
66
68
|
|
|
67
69
|
def ssh(server, command, print_output: false)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
retries = 0
|
|
71
|
+
|
|
72
|
+
public_ip = server.dig('public_net', 'ipv4', 'ip')
|
|
73
|
+
output = ''
|
|
70
74
|
|
|
71
75
|
params = { verify_host_key: (verify_host_key ? :always : :never) }
|
|
72
76
|
|
|
73
|
-
|
|
74
|
-
params[:keys] = [private_ssh_key_path]
|
|
75
|
-
end
|
|
77
|
+
params[:keys] = private_ssh_key_path && [private_ssh_key_path]
|
|
76
78
|
|
|
77
|
-
Net::SSH.start(public_ip,
|
|
78
|
-
session.exec!(command) do |
|
|
79
|
+
Net::SSH.start(public_ip, 'root', params) do |session|
|
|
80
|
+
session.exec!(command) do |_channel, _stream, data|
|
|
79
81
|
output << data
|
|
80
82
|
puts data if print_output
|
|
81
83
|
end
|
|
82
84
|
end
|
|
83
85
|
output.chop
|
|
84
86
|
rescue Net::SSH::Disconnect => e
|
|
85
|
-
|
|
87
|
+
retries += 1
|
|
88
|
+
retry unless retries > 15 || e.message =~ /Too many authentication failures/
|
|
86
89
|
rescue Net::SSH::ConnectionTimeout, Errno::ECONNREFUSED, Errno::ENETUNREACH, Errno::EHOSTUNREACH
|
|
87
|
-
|
|
90
|
+
retries += 1
|
|
91
|
+
retry if retries <= 15
|
|
88
92
|
rescue Net::SSH::AuthenticationFailed
|
|
89
|
-
puts
|
|
90
|
-
puts "Cannot continue: SSH authentication failed. Please ensure that the private SSH key is correct."
|
|
93
|
+
puts '\nCannot continue: SSH authentication failed. Please ensure that the private SSH key is correct.'
|
|
91
94
|
exit 1
|
|
92
95
|
rescue Net::SSH::HostKeyMismatch
|
|
93
|
-
puts
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
puts <<-MESSAGE
|
|
97
|
+
Cannot continue: Unable to SSH into server with IP #{public_ip} because the existing fingerprint in the known_hosts file does not match that of the actual host key.\n
|
|
98
|
+
This is due to a security check but can also happen when creating a new server that gets assigned the same IP address as another server you've owned in the past.\n
|
|
99
|
+
If are sure no security is being violated here and you're just creating new servers, you can eiher remove the relevant lines from your known_hosts (see IPs from the cloud console) or disable host key verification by setting the option 'verify_host_key' to false in the configuration file for the cluster.
|
|
100
|
+
MESSAGE
|
|
97
101
|
exit 1
|
|
98
102
|
end
|
|
99
103
|
end
|
data/lib/hetzner.rb
CHANGED
metadata
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hetzner-k3s
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vito Botta
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-
|
|
11
|
+
date: 2022-02-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
14
|
+
name: bcrypt_pbkdf
|
|
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: ed25519
|
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
|
16
30
|
requirements:
|
|
17
31
|
- - ">="
|
|
@@ -67,7 +81,7 @@ dependencies:
|
|
|
67
81
|
- !ruby/object:Gem::Version
|
|
68
82
|
version: '0'
|
|
69
83
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
84
|
+
name: subprocess
|
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
|
72
86
|
requirements:
|
|
73
87
|
- - ">="
|
|
@@ -81,7 +95,7 @@ dependencies:
|
|
|
81
95
|
- !ruby/object:Gem::Version
|
|
82
96
|
version: '0'
|
|
83
97
|
- !ruby/object:Gem::Dependency
|
|
84
|
-
name:
|
|
98
|
+
name: thor
|
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
|
86
100
|
requirements:
|
|
87
101
|
- - ">="
|
|
@@ -95,13 +109,13 @@ dependencies:
|
|
|
95
109
|
- !ruby/object:Gem::Version
|
|
96
110
|
version: '0'
|
|
97
111
|
- !ruby/object:Gem::Dependency
|
|
98
|
-
name:
|
|
112
|
+
name: rubocop
|
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
|
100
114
|
requirements:
|
|
101
115
|
- - ">="
|
|
102
116
|
- !ruby/object:Gem::Version
|
|
103
117
|
version: '0'
|
|
104
|
-
type: :
|
|
118
|
+
type: :development
|
|
105
119
|
prerelease: false
|
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
|
107
121
|
requirements:
|
|
@@ -119,6 +133,7 @@ extra_rdoc_files: []
|
|
|
119
133
|
files:
|
|
120
134
|
- ".gitignore"
|
|
121
135
|
- ".rspec"
|
|
136
|
+
- ".rubocop.yml"
|
|
122
137
|
- ".ruby-version"
|
|
123
138
|
- ".travis.yml"
|
|
124
139
|
- CODE_OF_CONDUCT.md
|
|
@@ -129,8 +144,8 @@ files:
|
|
|
129
144
|
- README.md
|
|
130
145
|
- Rakefile
|
|
131
146
|
- bin/build.sh
|
|
132
|
-
- bin/console
|
|
133
|
-
- bin/setup
|
|
147
|
+
- bin/console.sh
|
|
148
|
+
- bin/setup.sh
|
|
134
149
|
- cluster_config.yaml.example
|
|
135
150
|
- entrypoint.sh
|
|
136
151
|
- exe/hetzner-k3s
|
|
@@ -155,6 +170,7 @@ metadata:
|
|
|
155
170
|
homepage_uri: https://github.com/vitobotta/hetzner-k3s
|
|
156
171
|
source_code_uri: https://github.com/vitobotta/hetzner-k3s
|
|
157
172
|
changelog_uri: https://github.com/vitobotta/hetzner-k3s
|
|
173
|
+
rubygems_mfa_required: 'true'
|
|
158
174
|
post_install_message:
|
|
159
175
|
rdoc_options: []
|
|
160
176
|
require_paths:
|
|
@@ -163,7 +179,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
163
179
|
requirements:
|
|
164
180
|
- - ">="
|
|
165
181
|
- !ruby/object:Gem::Version
|
|
166
|
-
version:
|
|
182
|
+
version: 3.1.0
|
|
167
183
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
184
|
requirements:
|
|
169
185
|
- - ">="
|