hetzner-k3s 0.5.9 → 0.6.0.pre1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 65fe7fa7e6bdeeb49175cfb92184ab320ef8ac40a3aa03f921f1e5fda1b172d7
4
- data.tar.gz: 1448919374ef90f7614580251b28000c470b0ed7fba39724e8953f29f176c1bb
3
+ metadata.gz: 47fa67797132b81c083283de99f93c4a0ce0b4119a1e575f74fb98550fd1ef10
4
+ data.tar.gz: e6fb4fcf848b988b23359037d4d544e12f7866ad9993c7eb560708b4ebf94a7f
5
5
  SHA512:
6
- metadata.gz: 15f783adb7408a1df5c3e9a114d9dcbc61830ead33acb7bc162ca935b6cdcfe26507e2c404d48c831cae600fe765adc31e686b511c4f675c561d6eb9acabafd2
7
- data.tar.gz: df10039025e735d6a73c84fb60516d70bc0aa48220db1bab9d99dd30caad87339ba6be83e2d3f1029f40f95719a6fcde5784956c86ef20d524b67d504f93920a
6
+ metadata.gz: 7649a2467a8b84711f30f1ba4867a662207e3dc45cbdf26589b96194bb14c6c120b7f4d81edbc1aab46416704926b86b95f3d39cc283c98ad33bdc0642a5f3e8
7
+ data.tar.gz: c4e8226ad4e473a3dc7262dde4389fae8816ca0378f644288cbf1722b9fc342ce0a0a28d5251e4907e4c21170e943159ce326e2afd61f97eabd1853cb135e7b6
@@ -0,0 +1,32 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - '*'
7
+
8
+ jobs:
9
+ mcos:
10
+ runs-on: macos-12
11
+ steps:
12
+ - uses: actions/checkout@v3
13
+
14
+ - uses: ruby/setup-ruby@v1
15
+ with:
16
+ ruby-version: '2.7.1'
17
+
18
+ - name: Get ruby-packer
19
+ run: |
20
+ curl -o rubyc-macos https://github.com/pmq20/ruby-packer/releases/download/darwin-x64/rubyc
21
+ chmod +x rubyc-macos
22
+
23
+ - name: Build for macOS
24
+ run: |
25
+ env CC="xcrun clang -mmacosx-version-min=10.10 -Wno-implicit-function-declaration" time ./rubyc-macos -r ./ -o $GITHUB_WORKSPACE/hetzner-k3s-macos exe/hetzner-k3s
26
+ chmod +x hetzner-k3s-macos
27
+
28
+ - uses: ncipollo/release-action@v1
29
+ with:
30
+ tag: v$(ruby -r ./lib/hetzner/k3s/version -e 'puts Hetzner::K3s::VERSION')
31
+ artifacts: "hetzner-k3s-macos"
32
+ token: ${{ secrets.GITHUB_TOKEN }}
data/.gitignore CHANGED
@@ -11,3 +11,5 @@
11
11
  .rspec_status
12
12
  /kubeconfig
13
13
  /cluster_config.yaml
14
+ dist/hetzner-k3s.jar
15
+ dist/hetzner-k3s
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-3.1.2
1
+ ruby-2.7.1
data/Gemfile CHANGED
@@ -5,5 +5,16 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in k3s.gemspec
6
6
  gemspec
7
7
 
8
- gem 'rake', '~> 12.0'
9
- gem 'rspec', '~> 3.0'
8
+ # platforms :jruby do
9
+ # gem 'rake', '~> 12.0'
10
+ # gem 'rspec', '~> 3.0'
11
+
12
+ # gem 'childprocess'
13
+ # gem 'ed25519'
14
+ # gem 'http'
15
+ # gem 'jruby-openssl'
16
+ # gem 'net-ssh'
17
+ # gem 'sshkey'
18
+ # gem 'thor'
19
+ # gem 'http-parser'
20
+ # end
data/Gemfile.lock CHANGED
@@ -1,90 +1,59 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hetzner-k3s (0.5.7)
4
+ hetzner-k3s (0.5.9)
5
5
  bcrypt_pbkdf
6
+ childprocess
6
7
  ed25519
7
- http
8
+ httparty
8
9
  net-ssh
9
10
  sshkey
10
- subprocess
11
11
  thor
12
12
 
13
13
  GEM
14
14
  remote: https://rubygems.org/
15
15
  specs:
16
- addressable (2.8.0)
17
- public_suffix (>= 2.0.2, < 5.0)
18
16
  ast (2.4.2)
19
17
  bcrypt_pbkdf (1.1.0)
20
- diff-lcs (1.4.4)
21
- domain_name (0.5.20190701)
22
- unf (>= 0.0.5, < 1.0.0)
18
+ childprocess (4.1.0)
23
19
  ed25519 (1.3.0)
24
- ffi (1.15.5)
25
- ffi-compiler (1.0.1)
26
- ffi (>= 1.0.0)
27
- rake
28
- http (4.4.1)
29
- addressable (~> 2.3)
30
- http-cookie (~> 1.0)
31
- http-form_data (~> 2.2)
32
- http-parser (~> 1.2.0)
33
- http-cookie (1.0.5)
34
- domain_name (~> 0.5)
35
- http-form_data (2.3.0)
36
- http-parser (1.2.3)
37
- ffi-compiler (>= 1.0, < 2.0)
20
+ httparty (0.20.0)
21
+ mime-types (~> 3.0)
22
+ multi_xml (>= 0.5.2)
23
+ mime-types (3.4.1)
24
+ mime-types-data (~> 3.2015)
25
+ mime-types-data (3.2022.0105)
26
+ multi_xml (0.6.0)
38
27
  net-ssh (6.1.0)
39
- parallel (1.21.0)
40
- parser (3.1.0.0)
28
+ parallel (1.20.1)
29
+ parser (3.1.2.1)
41
30
  ast (~> 2.4.1)
42
- public_suffix (4.0.7)
43
31
  rainbow (3.1.1)
44
- rake (12.3.3)
45
- regexp_parser (2.2.0)
32
+ regexp_parser (2.5.0)
46
33
  rexml (3.2.5)
47
- rspec (3.10.0)
48
- rspec-core (~> 3.10.0)
49
- rspec-expectations (~> 3.10.0)
50
- rspec-mocks (~> 3.10.0)
51
- rspec-core (3.10.1)
52
- rspec-support (~> 3.10.0)
53
- rspec-expectations (3.10.1)
54
- diff-lcs (>= 1.2.0, < 2.0)
55
- rspec-support (~> 3.10.0)
56
- rspec-mocks (3.10.2)
57
- diff-lcs (>= 1.2.0, < 2.0)
58
- rspec-support (~> 3.10.0)
59
- rspec-support (3.10.2)
60
- rubocop (1.25.1)
34
+ rubocop (1.12.1)
61
35
  parallel (~> 1.10)
62
- parser (>= 3.1.0.0)
36
+ parser (>= 3.0.0.0)
63
37
  rainbow (>= 2.2.2, < 4.0)
64
38
  regexp_parser (>= 1.8, < 3.0)
65
39
  rexml
66
- rubocop-ast (>= 1.15.1, < 2.0)
40
+ rubocop-ast (>= 1.2.0, < 2.0)
67
41
  ruby-progressbar (~> 1.7)
68
42
  unicode-display_width (>= 1.4.0, < 3.0)
69
- rubocop-ast (1.15.1)
70
- parser (>= 3.0.1.1)
43
+ rubocop-ast (1.4.1)
44
+ parser (>= 2.7.1.5)
71
45
  ruby-progressbar (1.11.0)
72
46
  sshkey (2.0.0)
73
- subprocess (1.5.5)
74
47
  thor (1.2.1)
75
- unf (0.1.4)
76
- unf_ext
77
- unf_ext (0.0.8.2)
78
- unicode-display_width (2.1.0)
48
+ unicode-display_width (2.2.0)
79
49
 
80
50
  PLATFORMS
81
51
  ruby
52
+ x86_64-darwin-21
82
53
 
83
54
  DEPENDENCIES
84
55
  hetzner-k3s!
85
- rake (~> 12.0)
86
- rspec (~> 3.0)
87
56
  rubocop
88
57
 
89
58
  BUNDLED WITH
90
- 2.3.14
59
+ 2.3.21
data/bin/build.sh CHANGED
@@ -2,11 +2,17 @@
2
2
 
3
3
  set -e
4
4
 
5
- IMAGE="vitobotta/hetzner-k3s"
5
+ # IMAGE="vitobotta/hetzner-k3s"
6
6
 
7
- docker build -t ${IMAGE}:v0.5.9 \
8
- --platform=linux/amd64 \
9
- --cache-from ${IMAGE}:v0.5.8 \
10
- --build-arg BUILDKIT_INLINE_CACHE=1 .
7
+ # docker build -t ${IMAGE}:v0.5.9 \
8
+ # --platform=linux/amd64 \
9
+ # --cache-from ${IMAGE}:v0.5.8 \
10
+ # --build-arg BUILDKIT_INLINE_CACHE=1 .
11
11
 
12
- docker push vitobotta/hetzner-k3s:v0.5.9
12
+ # docker push vitobotta/hetzner-k3s:v0.5.9
13
+
14
+ warble
15
+
16
+ echo "#!/usr/bin/env java -jar" > dist/hetzner-k3s
17
+ cat dist/hetzner-k3s.jar >> dist/hetzner-k3s
18
+ chmod +x dist/hetzner-k3s
data/config/warble.rb ADDED
@@ -0,0 +1,182 @@
1
+ # Disable Rake-environment-task framework detection by uncommenting/setting to false
2
+ # Warbler.framework_detection = false
3
+
4
+ # Warbler web application assembly configuration file
5
+ Warbler::Config.new do |config|
6
+ # Features: additional options controlling how the jar is built.
7
+ # Currently the following features are supported:
8
+ # - *gemjar*: package the gem repository in a jar file in WEB-INF/lib
9
+ # - *executable*: embed a web server and make the war executable
10
+ # - *runnable*: allows to run bin scripts e.g. `java -jar my.war -S rake -T`
11
+ # - *compiled*: compile .rb files to .class files
12
+ config.features = %w(executable runnable compiled)
13
+
14
+ # Application directories to be included in the webapp.
15
+ config.dirs = %w(bin config exe lib)
16
+
17
+ # Additional files/directories to include, above those in config.dirs
18
+ # config.includes = FileList["db"]
19
+
20
+ # Additional files/directories to exclude
21
+ # config.excludes = FileList["lib/tasks/*"]
22
+
23
+ # Additional Java .jar files to include. Note that if .jar files are placed
24
+ # in lib (and not otherwise excluded) then they need not be mentioned here.
25
+ # JRuby and JRuby-Rack are pre-loaded in this list. Be sure to include your
26
+ # own versions if you directly set the value
27
+ # config.java_libs += FileList["lib/java/*.jar"]
28
+
29
+ # Loose Java classes and miscellaneous files to be included.
30
+ # config.java_classes = FileList["target/classes/**.*"]
31
+
32
+ # One or more pathmaps defining how the java classes should be copied into
33
+ # the archive. The example pathmap below accompanies the java_classes
34
+ # configuration above. See http://rake.rubyforge.org/classes/String.html#M000017
35
+ # for details of how to specify a pathmap.
36
+ # config.pathmaps.java_classes << "%{target/classes/,}p"
37
+
38
+ # Bundler support is built-in. If Warbler finds a Gemfile in the
39
+ # project directory, it will be used to collect the gems to bundle
40
+ # in your application. If you wish to explicitly disable this
41
+ # functionality, uncomment here.
42
+ config.bundler = true
43
+
44
+ # An array of Bundler groups to avoid including in the war file.
45
+ # Defaults to ["development", "test", "assets"].
46
+ # config.bundle_without = []
47
+
48
+ # Other gems to be included. If you don't use Bundler or a gemspec
49
+ # file, you need to tell Warbler which gems your application needs
50
+ # so that they can be packaged in the archive.
51
+ # For Rails applications, the Rails gems are included by default
52
+ # unless the vendor/rails directory is present.
53
+ # config.gems += ["activerecord-jdbcmysql-adapter", "jruby-openssl"]
54
+ # config.gems << "tzinfo"
55
+
56
+ # Uncomment this if you don't want to package rails gem.
57
+ # config.gems -= ["rails"]
58
+
59
+ # The most recent versions of gems are used.
60
+ # You can specify versions of gems by using a hash assignment:
61
+ # config.gems["rails"] = "4.2.5"
62
+
63
+ # You can also use regexps or Gem::Dependency objects for flexibility or
64
+ # finer-grained control.
65
+ # config.gems << /^sinatra-/
66
+ # config.gems << Gem::Dependency.new("sinatra", "= 1.4.7")
67
+
68
+ # Include gem dependencies not mentioned specifically. Default is
69
+ # true, uncomment to turn off.
70
+ # config.gem_dependencies = false
71
+
72
+ # Array of regular expressions matching relative paths in gems to be
73
+ # excluded from the war. Defaults to empty, but you can set it like
74
+ # below, which excludes test files.
75
+ # config.gem_excludes = [/^(test|spec)\//]
76
+
77
+ # Pathmaps for controlling how application files are copied into the archive
78
+ # config.pathmaps.application = ["WEB-INF/%p"]
79
+
80
+ # Name of the archive (without the extension). Defaults to the basename
81
+ # of the project directory.
82
+ config.jar_name = "hetzner-k3s"
83
+
84
+ # File extension for the archive. Defaults to either 'jar' or 'war'.
85
+ config.jar_extension = "jar"
86
+
87
+ # Destionation for the created archive. Defaults to project's root directory.
88
+ config.autodeploy_dir = "dist/"
89
+
90
+ # Name of the MANIFEST.MF template for the war file. Defaults to a simple
91
+ # MANIFEST.MF that contains the version of Warbler used to create the war file.
92
+ # config.manifest_file = "config/MANIFEST.MF"
93
+
94
+ # When using the 'compiled' feature and specified, only these Ruby
95
+ # files will be compiled. Default is to compile all \.rb files in
96
+ # the application.
97
+ # config.compiled_ruby_files = FileList['app/**/*.rb']
98
+
99
+ # Determines if ruby files in supporting gems will be compiled.
100
+ # Ignored unless compile feature is used.
101
+ config.compile_gems = true
102
+
103
+ # When set it specify the bytecode version for compiled class files
104
+ # config.bytecode_version = "1.6"
105
+
106
+ # When set to true, Warbler will override the value of ENV['GEM_HOME'] even it
107
+ # has already been set. When set to false it will use any existing value of
108
+ # GEM_HOME if it is set.
109
+ # config.override_gem_home = true
110
+
111
+ # Allows for specifing custom executables
112
+ # config.executable = ["exe/hetzner-k3s"]
113
+
114
+ # Sets default (prefixed) parameters for the executables
115
+ # config.executable_params = "do:something"
116
+
117
+ # If set to true, moves jar files into WEB-INF/lib. Prior to version 1.4.2 of Warbler this was done
118
+ # by default. But since 1.4.2 this config defaults to false. It may need to be set to true for
119
+ # web servers that do not explode the WAR file.
120
+ # Alternatively, this option can be set to a regular expression, which will
121
+ # act as a jar selector -- only jar files that match the pattern will be
122
+ # included in the archive.
123
+ # config.move_jars_to_webinf_lib = false
124
+
125
+ # === War files only below here ===
126
+
127
+ # Embedded webserver to use with the 'executable' feature. Currently supported
128
+ # webservers are:
129
+ # - *jetty* - Embedded Jetty from Eclipse
130
+ # config.webserver = 'jetty'
131
+
132
+ # Path to the pre-bundled gem directory inside the war file. Default
133
+ # is 'WEB-INF/gems'. Specify path if gems are already bundled
134
+ # before running Warbler. This also sets 'gem.path' inside web.xml.
135
+ # config.gem_path = "WEB-INF/vendor/bundler_gems"
136
+
137
+ # Files for WEB-INF directory (next to web.xml). This contains
138
+ # web.xml by default. If there is an .erb-File it will be processed
139
+ # with webxml-config. You may want to exclude this file via
140
+ # config.excludes.
141
+ # config.webinf_files += FileList["jboss-web.xml"]
142
+
143
+ # Files to be included in the root of the webapp. Note that files in public
144
+ # will have the leading 'public/' part of the path stripped during staging.
145
+ # config.public_html = FileList["public/**/*", "doc/**/*"]
146
+
147
+ # Pathmaps for controlling how public HTML files are copied into the .war
148
+ # config.pathmaps.public_html = ["%{public/,}p"]
149
+
150
+ # Value of RAILS_ENV for the webapp -- default as shown below
151
+ # config.webxml.rails.env = ENV['RAILS_ENV'] || 'production'
152
+
153
+ # Public ROOT mapping, by default assets are copied into .war ROOT directory.
154
+ # config.public.root = ''
155
+
156
+ # Application booter to use, either :rack or :rails (autodetected by default)
157
+ # config.webxml.booter = :rails
158
+
159
+ # When using the :rack booter, "Rackup" script to use.
160
+ # - For 'rackup.path', the value points to the location of the rackup
161
+ # script in the web archive file. You need to make sure this file
162
+ # gets included in the war, possibly by adding it to config.includes
163
+ # or config.webinf_files above.
164
+ # - For 'rackup', the rackup script you provide as an inline string
165
+ # is simply embedded in web.xml.
166
+ # The script is evaluated in a Rack::Builder to load the application.
167
+ # Examples:
168
+ # config.webxml.rackup.path = 'WEB-INF/hello.ru'
169
+ # config.webxml.rackup = %{require './lib/demo'; run Rack::Adapter::Camping.new(Demo)}
170
+ # config.webxml.rackup = require 'cgi' && CGI::escapeHTML(File.read("config.ru"))
171
+
172
+ # Control the pool of Rails runtimes. Leaving unspecified means
173
+ # the pool will grow as needed to service requests. It is recommended
174
+ # that you fix these values when running a production server!
175
+ # If you're using threadsafe! mode, you probably don't want to set these values,
176
+ # since 1 runtime(default for threadsafe mode) will be enough.
177
+ # config.webxml.jruby.min.runtimes = 2
178
+ # config.webxml.jruby.max.runtimes = 4
179
+
180
+ # JNDI data source name
181
+ # config.webxml.jndi = 'jdbc/rails'
182
+ end
data/exe/hetzner-k3s CHANGED
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+
3
6
  require_relative '../lib/hetzner/k3s/cli'
4
7
  Hetzner::K3s::CLI.start
data/hetzner-k3s.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = 'A CLI to create a Kubernetes cluster in Hetzner Cloud very quickly using k3s.'
13
13
  spec.homepage = 'https://github.com/vitobotta/hetzner-k3s'
14
14
  spec.license = 'MIT'
15
- spec.required_ruby_version = Gem::Requirement.new('>= 3.1.2')
15
+ spec.required_ruby_version = Gem::Requirement.new('~> 2.7.1')
16
16
 
17
17
  # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
18
18
 
@@ -20,12 +20,12 @@ Gem::Specification.new do |spec|
20
20
  spec.metadata['source_code_uri'] = 'https://github.com/vitobotta/hetzner-k3s'
21
21
  spec.metadata['changelog_uri'] = 'https://github.com/vitobotta/hetzner-k3s'
22
22
 
23
- spec.add_dependency 'bcrypt_pbkdf'
23
+ spec.add_dependency 'childprocess'
24
24
  spec.add_dependency 'ed25519'
25
- spec.add_dependency 'http'
25
+ spec.add_dependency 'httparty'
26
+ spec.add_dependency 'bcrypt_pbkdf'
26
27
  spec.add_dependency 'net-ssh'
27
28
  spec.add_dependency 'sshkey'
28
- spec.add_dependency 'subprocess'
29
29
  spec.add_dependency 'thor'
30
30
  spec.add_development_dependency 'rubocop'
31
31
 
@@ -12,19 +12,19 @@ module Hetzner
12
12
 
13
13
  def get(path)
14
14
  make_request do
15
- JSON.parse HTTP.headers(headers).get(BASE_URI + path).body
15
+ JSON.parse HTTParty.get(BASE_URI + path, headers: headers).body
16
16
  end
17
17
  end
18
18
 
19
19
  def post(path, data)
20
20
  make_request do
21
- HTTP.headers(headers).post(BASE_URI + path, json: data)
21
+ HTTParty.post(BASE_URI + path, body: data.to_json, headers: headers)
22
22
  end
23
23
  end
24
24
 
25
25
  def delete(path, id)
26
26
  make_request do
27
- HTTP.headers(headers).delete("#{BASE_URI}#{path}/#{id}")
27
+ HTTParty.delete("#{BASE_URI}#{path}/#{id}", headers: headers)
28
28
  end
29
29
  end
30
30
 
@@ -32,8 +32,8 @@ module Hetzner
32
32
 
33
33
  def headers
34
34
  {
35
- Authorization: "Bearer #{@token}",
36
- 'Content-Type': 'application/json'
35
+ 'Authorization' => "Bearer #{@token}",
36
+ 'Content-Type' => 'application/json'
37
37
  }
38
38
  end
39
39
 
@@ -106,7 +106,7 @@ module Hetzner
106
106
 
107
107
  {
108
108
  name: cluster_name,
109
- rules:
109
+ rules: rules
110
110
  }
111
111
  end
112
112
 
@@ -57,7 +57,7 @@ module Hetzner
57
57
  type: 'round_robin'
58
58
  },
59
59
  load_balancer_type: 'lb11',
60
- location:,
60
+ location: location,
61
61
  name: load_balancer_name,
62
62
  network: network_id,
63
63
  public_interface: true,
@@ -30,8 +30,8 @@ module Hetzner
30
30
 
31
31
  def delete
32
32
  if (network = find_network)
33
- if network["name"] == existing_network
34
- puts "Network existed before cluster, skipping."
33
+ if network['name'] == existing_network
34
+ puts 'Network existed before cluster, skipping.'
35
35
  else
36
36
  puts 'Deleting network...'
37
37
  hetzner_client.delete('/networks', network['id'])
@@ -37,7 +37,6 @@ module Hetzner
37
37
  else
38
38
  puts "Error creating server #{server_name}. Response details below:"
39
39
  puts
40
- p response
41
40
  end
42
41
  end
43
42
 
@@ -99,8 +98,8 @@ module Hetzner
99
98
  def server_config
100
99
  @server_config ||= {
101
100
  name: server_name,
102
- location:,
103
- image:,
101
+ location: location,
102
+ image: image,
104
103
  firewalls: [
105
104
  { firewall: firewall_id }
106
105
  ],
@@ -111,7 +110,7 @@ module Hetzner
111
110
  ssh_keys: [
112
111
  ssh_key_id
113
112
  ],
114
- user_data:,
113
+ user_data: user_data,
115
114
  labels: {
116
115
  cluster: cluster_name,
117
116
  role: (server_name =~ /master/ ? 'master' : 'worker')
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'thor'
4
- require 'http'
4
+ require 'openssl'
5
+ require 'httparty'
5
6
  require 'sshkey'
6
7
  require 'ipaddr'
7
8
  require 'open-uri'
@@ -27,14 +28,14 @@ module Hetzner
27
28
  option :config_file, required: true
28
29
  def create_cluster
29
30
  configuration.validate action: :create
30
- Cluster.new(configuration:).create
31
+ Cluster.new(configuration: configuration).create
31
32
  end
32
33
 
33
34
  desc 'delete-cluster', 'Delete an existing k3s cluster in Hetzner Cloud'
34
35
  option :config_file, required: true
35
36
  def delete_cluster
36
37
  configuration.validate action: :delete
37
- Cluster.new(configuration:).delete
38
+ Cluster.new(configuration: configuration).delete
38
39
  end
39
40
 
40
41
  desc 'upgrade-cluster', 'Upgrade an existing k3s cluster in Hetzner Cloud to a new version'
@@ -43,7 +44,7 @@ module Hetzner
43
44
  option :force, default: 'false'
44
45
  def upgrade_cluster
45
46
  configuration.validate action: :upgrade
46
- Cluster.new(configuration:).upgrade(new_k3s_version: options[:new_k3s_version], config_file: options[:config_file])
47
+ Cluster.new(configuration: configuration).upgrade(new_k3s_version: options[:new_k3s_version], config_file: options[:config_file])
47
48
  end
48
49
 
49
50
  desc 'releases', 'List available k3s releases'
@@ -59,7 +60,7 @@ module Hetzner
59
60
 
60
61
  def configuration
61
62
  @configuration ||= begin
62
- config = ::Hetzner::Configuration.new(options:)
63
+ config = ::Hetzner::Configuration.new(options: options)
63
64
  @hetzner_token = config.hetzner_token
64
65
  config
65
66
  end
@@ -4,7 +4,7 @@ require 'net/ssh'
4
4
  require 'securerandom'
5
5
  require 'base64'
6
6
  require 'timeout'
7
- require 'subprocess'
7
+ require 'fileutils'
8
8
 
9
9
  require_relative '../infra/client'
10
10
  require_relative '../infra/firewall'
@@ -93,7 +93,7 @@ class Cluster
93
93
  end
94
94
 
95
95
  def latest_k3s_version
96
- response = HTTP.get('https://api.github.com/repos/k3s-io/k3s/tags').body
96
+ response = HTTParty.get('https://api.github.com/repos/k3s-io/k3s/tags').body
97
97
  JSON.parse(response).first['name']
98
98
  end
99
99
 
@@ -103,22 +103,22 @@ class Cluster
103
103
  end
104
104
 
105
105
  def delete_placement_groups
106
- Hetzner::PlacementGroup.new(hetzner_client:, cluster_name:).delete
106
+ Hetzner::PlacementGroup.new(hetzner_client: hetzner_client, cluster_name: cluster_name).delete
107
107
 
108
108
  worker_node_pools.each do |pool|
109
109
  pool_name = pool['name']
110
- Hetzner::PlacementGroup.new(hetzner_client:, cluster_name:, pool_name:).delete
110
+ Hetzner::PlacementGroup.new(hetzner_client: hetzner_client, cluster_name: cluster_name, pool_name: pool_name).delete
111
111
  end
112
112
  end
113
113
 
114
114
  def delete_resources
115
- Hetzner::LoadBalancer.new(hetzner_client:, cluster_name:).delete(high_availability: (masters.size > 1))
115
+ Hetzner::LoadBalancer.new(hetzner_client: hetzner_client, cluster_name: cluster_name).delete(high_availability: (masters.size > 1))
116
116
 
117
- Hetzner::Firewall.new(hetzner_client:, cluster_name:).delete(all_servers)
117
+ Hetzner::Firewall.new(hetzner_client: hetzner_client, cluster_name: cluster_name).delete(all_servers)
118
118
 
119
- Hetzner::Network.new(hetzner_client:, cluster_name:, existing_network:).delete
119
+ Hetzner::Network.new(hetzner_client: hetzner_client, cluster_name: cluster_name, existing_network: existing_network).delete
120
120
 
121
- Hetzner::SSHKey.new(hetzner_client:, cluster_name:).delete(public_ssh_key_path:)
121
+ Hetzner::SSHKey.new(hetzner_client: hetzner_client, cluster_name: cluster_name).delete(public_ssh_key_path: public_ssh_key_path)
122
122
 
123
123
  delete_placement_groups
124
124
  delete_servers
@@ -202,14 +202,14 @@ class Cluster
202
202
  selected_version_index = available_k3s_releases.find_index(k3s_version)
203
203
 
204
204
  flannel_wireguard = if enable_encryption
205
- if selected_version_index >= wireguard_native_min_version_index
206
- ' --flannel-backend=wireguard-native '
207
- else
208
- ' --flannel-backend=wireguard '
209
- end
210
- else
211
- ' '
212
- end
205
+ if selected_version_index >= wireguard_native_min_version_index
206
+ ' --flannel-backend=wireguard-native '
207
+ else
208
+ ' --flannel-backend=wireguard '
209
+ end
210
+ else
211
+ ' '
212
+ end
213
213
 
214
214
  extra_args = "#{kube_api_server_args_list} #{kube_scheduler_args_list} #{kube_controller_manager_args_list} #{kube_cloud_controller_manager_args_list} #{kubelet_args_list} #{kube_proxy_args_list}"
215
215
  taint = schedule_workloads_on_masters? ? ' ' : ' --node-taint CriticalAddonsOnly=true:NoExecute '
@@ -423,7 +423,7 @@ class Cluster
423
423
 
424
424
  masters.each do |master|
425
425
  master_private_ip = master['private_net'][0]['ip']
426
- sans << " --tls-san=#{master_private_ip} "
426
+ sans += " --tls-san=#{master_private_ip} "
427
427
  end
428
428
 
429
429
  sans
@@ -473,7 +473,7 @@ class Cluster
473
473
 
474
474
  def placement_group_id(pool_name = nil)
475
475
  @placement_groups ||= {}
476
- @placement_groups[pool_name || '__masters__'] ||= Hetzner::PlacementGroup.new(hetzner_client:, cluster_name:, pool_name:).create
476
+ @placement_groups[pool_name || '__masters__'] ||= Hetzner::PlacementGroup.new(hetzner_client: hetzner_client, cluster_name: cluster_name, pool_name: pool_name).create
477
477
  end
478
478
 
479
479
  def master_instance_type
@@ -485,15 +485,15 @@ class Cluster
485
485
  end
486
486
 
487
487
  def firewall_id
488
- @firewall_id ||= Hetzner::Firewall.new(hetzner_client:, cluster_name:).create(high_availability: (masters_count > 1), ssh_networks:, api_networks:)
488
+ @firewall_id ||= Hetzner::Firewall.new(hetzner_client: hetzner_client, cluster_name: cluster_name).create(high_availability: (masters_count > 1), ssh_networks: ssh_networks, api_networks: api_networks)
489
489
  end
490
490
 
491
491
  def network_id
492
- @network_id ||= Hetzner::Network.new(hetzner_client:, cluster_name:, existing_network:).create(location: masters_location)
492
+ @network_id ||= Hetzner::Network.new(hetzner_client: hetzner_client, cluster_name: cluster_name, existing_network: existing_network).create(location: masters_location)
493
493
  end
494
494
 
495
495
  def ssh_key_id
496
- @ssh_key_id ||= Hetzner::SSHKey.new(hetzner_client:, cluster_name:).create(public_ssh_key_path:)
496
+ @ssh_key_id ||= Hetzner::SSHKey.new(hetzner_client: hetzner_client, cluster_name: cluster_name).create(public_ssh_key_path: public_ssh_key_path)
497
497
  end
498
498
 
499
499
  def master_definitions_for_create
@@ -504,13 +504,13 @@ class Cluster
504
504
  instance_type: master_instance_type,
505
505
  instance_id: "master#{i + 1}",
506
506
  location: masters_location,
507
- placement_group_id:,
508
- firewall_id:,
509
- network_id:,
510
- ssh_key_id:,
511
- image:,
512
- additional_packages:,
513
- additional_post_create_commands:
507
+ placement_group_id: placement_group_id,
508
+ firewall_id: firewall_id,
509
+ network_id: network_id,
510
+ ssh_key_id: ssh_key_id,
511
+ image: image,
512
+ additional_packages: additional_packages,
513
+ additional_post_create_commands: additional_post_create_commands
514
514
  }
515
515
  end
516
516
 
@@ -544,12 +544,12 @@ class Cluster
544
544
  instance_id: "pool-#{worker_node_pool_name}-worker#{i + 1}",
545
545
  placement_group_id: placement_group_id(worker_node_pool_name),
546
546
  location: worker_location,
547
- firewall_id:,
548
- network_id:,
549
- ssh_key_id:,
550
- image:,
551
- additional_packages:,
552
- additional_post_create_commands:
547
+ firewall_id: firewall_id,
548
+ network_id: network_id,
549
+ ssh_key_id: ssh_key_id,
550
+ image: image,
551
+ additional_packages: additional_packages,
552
+ additional_post_create_commands: additional_post_create_commands
553
553
  }
554
554
  end
555
555
 
@@ -557,7 +557,7 @@ class Cluster
557
557
  end
558
558
 
559
559
  def create_load_balancer
560
- Hetzner::LoadBalancer.new(hetzner_client:, cluster_name:).create(location: masters_location, network_id:)
560
+ Hetzner::LoadBalancer.new(hetzner_client: hetzner_client, cluster_name: cluster_name).create(location: masters_location, network_id: network_id)
561
561
  end
562
562
 
563
563
  def server_configs
@@ -577,7 +577,7 @@ class Cluster
577
577
 
578
578
  threads = server_configs.map do |server_config|
579
579
  Thread.new do
580
- servers << Hetzner::Server.new(hetzner_client:, cluster_name:).create(**server_config)
580
+ servers << Hetzner::Server.new(hetzner_client: hetzner_client, cluster_name: cluster_name).create(**server_config)
581
581
  end
582
582
  end
583
583
 
@@ -599,7 +599,7 @@ class Cluster
599
599
  def delete_servers
600
600
  threads = all_servers.map do |server|
601
601
  Thread.new do
602
- Hetzner::Server.new(hetzner_client:, cluster_name:).delete(server_name: server['name'])
602
+ Hetzner::Server.new(hetzner_client: hetzner_client, cluster_name: cluster_name).delete(server_name: server['name'])
603
603
  end
604
604
  end
605
605
 
@@ -659,6 +659,6 @@ class Cluster
659
659
  end
660
660
 
661
661
  def existing_network
662
- configuration["existing_network"]
662
+ configuration['existing_network']
663
663
  end
664
664
  end
@@ -92,12 +92,10 @@ module Hetzner
92
92
  configuration
93
93
  end
94
94
 
95
- private
96
-
97
- attr_reader :configuration, :errors, :options
95
+ private_class_method
98
96
 
99
97
  def self.fetch_releases(url)
100
- response = HTTP.get(url)
98
+ response = HTTParty.get(url)
101
99
  [response, JSON.parse(response.body).map { |hash| hash['name'] }]
102
100
  end
103
101
 
@@ -121,13 +119,17 @@ module Hetzner
121
119
  end
122
120
  end
123
121
 
122
+ private
123
+
124
+ attr_reader :configuration, :errors, :options
125
+
124
126
  def validate_create
125
127
  validate_public_ssh_key
126
128
  validate_private_ssh_key
127
129
  validate_ssh_allowed_networks
128
130
  validate_api_allowed_networks
129
131
  validate_masters_location
130
- validate_k3s_version
132
+ # validate_k3s_version
131
133
  validate_masters
132
134
  validate_worker_node_pools
133
135
  validate_verify_host_key
@@ -144,7 +146,7 @@ module Hetzner
144
146
 
145
147
  def validate_upgrade
146
148
  validate_kubeconfig_path_must_exist
147
- validate_new_k3s_version
149
+ # validate_new_k3s_version
148
150
  end
149
151
 
150
152
  def validate_public_ssh_key
@@ -399,7 +401,7 @@ module Hetzner
399
401
 
400
402
  begin
401
403
  token = hetzner_token
402
- @hetzner_client = Hetzner::Client.new(token:)
404
+ @hetzner_client = Hetzner::Client.new(token: token)
403
405
  response = hetzner_client.get('/locations')
404
406
  error_code = response.dig('error', 'code')
405
407
  @valid = error_code != 'unauthorized'
@@ -472,13 +474,13 @@ module Hetzner
472
474
  end
473
475
 
474
476
  def validate_existing_network
475
- if configuration["existing_network"]
476
- existing_network = Hetzner::Network.new(hetzner_client:, cluster_name: configuration["cluster_name"], existing_network: configuration["existing_network"]).get
477
+ return unless configuration['existing_network']
477
478
 
478
- unless existing_network
479
- @errors << "You have specified that you want to use the existing network named '#{configuration["existing_network"]} but this network doesn't exist"
480
- end
481
- end
479
+ existing_network = Hetzner::Network.new(hetzner_client: hetzner_client, cluster_name: configuration['cluster_name'], existing_network: configuration['existing_network']).get
480
+
481
+ return if existing_network
482
+
483
+ @errors << "You have specified that you want to use the existing network named '#{configuration['existing_network']} but this network doesn't exist"
482
484
  end
483
485
  end
484
486
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Hetzner
4
4
  module K3s
5
- VERSION = '0.5.9'
5
+ VERSION = '0.6.0.pre1'
6
6
  end
7
7
  end
data/lib/hetzner/utils.rb CHANGED
@@ -1,5 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ Net::SSH::Transport::Algorithms::ALGORITHMS.values.each { |algs| algs.reject! { |a| a =~ /^ecd(sa|h)-sha2/ } }
4
+ Net::SSH::KnownHosts::SUPPORTED_TYPE.reject! { |t| t =~ /^ecd(sa|h)-sha2/ }
5
+
6
+ require 'childprocess'
7
+
3
8
  module Utils
4
9
  CMD_FILE_PATH = '/tmp/cli.cmd'
5
10
 
@@ -19,8 +24,6 @@ module Utils
19
24
  end
20
25
 
21
26
  def run(command, kubeconfig_path:)
22
- env = ENV.to_hash.merge({ 'KUBECONFIG' => kubeconfig_path })
23
-
24
27
  write_file CMD_FILE_PATH, <<-CONTENT
25
28
  set -euo pipefail
26
29
  #{command}
@@ -29,20 +32,19 @@ module Utils
29
32
  FileUtils.chmod('+x', CMD_FILE_PATH)
30
33
 
31
34
  begin
32
- process = nil
35
+ process = ChildProcess.build('bash', '-c', CMD_FILE_PATH)
36
+ process.io.inherit!
37
+ process.environment['KUBECONFIG'] = kubeconfig_path
38
+ process.environment['HCLOUD_TOKEN'] = ENV.fetch('HCLOUD_TOKEN', '')
33
39
 
34
40
  at_exit do
35
- process&.send_signal('SIGTERM')
41
+ process.stop
36
42
  rescue Errno::ESRCH, Interrupt
37
43
  # ignore
38
44
  end
39
45
 
40
- Subprocess.check_call(['bash', '-c', CMD_FILE_PATH], env:) do |p|
41
- process = p
42
- end
43
- rescue Subprocess::NonZeroExit
44
- puts 'Command failed: non-zero exit code'
45
- exit 1
46
+ process.start
47
+ process.wait
46
48
  rescue Interrupt
47
49
  puts 'Command interrupted'
48
50
  exit 1
@@ -86,6 +88,13 @@ module Utils
86
88
  end
87
89
  end
88
90
  output.chop
91
+ # rescue StandardError => e
92
+ # p [e.class, e.message]
93
+ # retries += 1
94
+ # retry unless retries > 15 || e.message =~ /Bad file descriptor/
95
+ rescue Timeout::Error, IOError, Errno::EBADF
96
+ retries += 1
97
+ retry unless retries > 15
89
98
  rescue Net::SSH::Disconnect => e
90
99
  retries += 1
91
100
  retry unless retries > 15 || e.message =~ /Too many authentication failures/
metadata CHANGED
@@ -1,122 +1,122 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hetzner-k3s
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.9
4
+ version: 0.6.0.pre1
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-08-12 00:00:00.000000000 Z
11
+ date: 2022-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bcrypt_pbkdf
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
18
  version: '0'
20
- type: :runtime
19
+ name: childprocess
21
20
  prerelease: false
21
+ type: :runtime
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: ed25519
29
28
  requirement: !ruby/object:Gem::Requirement
30
29
  requirements:
31
30
  - - ">="
32
31
  - !ruby/object:Gem::Version
33
32
  version: '0'
34
- type: :runtime
33
+ name: ed25519
35
34
  prerelease: false
35
+ type: :runtime
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: http
43
42
  requirement: !ruby/object:Gem::Requirement
44
43
  requirements:
45
44
  - - ">="
46
45
  - !ruby/object:Gem::Version
47
46
  version: '0'
48
- type: :runtime
47
+ name: httparty
49
48
  prerelease: false
49
+ type: :runtime
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: net-ssh
57
56
  requirement: !ruby/object:Gem::Requirement
58
57
  requirements:
59
58
  - - ">="
60
59
  - !ruby/object:Gem::Version
61
60
  version: '0'
62
- type: :runtime
61
+ name: bcrypt_pbkdf
63
62
  prerelease: false
63
+ type: :runtime
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: sshkey
71
70
  requirement: !ruby/object:Gem::Requirement
72
71
  requirements:
73
72
  - - ">="
74
73
  - !ruby/object:Gem::Version
75
74
  version: '0'
76
- type: :runtime
75
+ name: net-ssh
77
76
  prerelease: false
77
+ type: :runtime
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: subprocess
85
84
  requirement: !ruby/object:Gem::Requirement
86
85
  requirements:
87
86
  - - ">="
88
87
  - !ruby/object:Gem::Version
89
88
  version: '0'
90
- type: :runtime
89
+ name: sshkey
91
90
  prerelease: false
91
+ type: :runtime
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: thor
99
98
  requirement: !ruby/object:Gem::Requirement
100
99
  requirements:
101
100
  - - ">="
102
101
  - !ruby/object:Gem::Version
103
102
  version: '0'
104
- type: :runtime
103
+ name: thor
105
104
  prerelease: false
105
+ type: :runtime
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: rubocop
113
112
  requirement: !ruby/object:Gem::Requirement
114
113
  requirements:
115
114
  - - ">="
116
115
  - !ruby/object:Gem::Version
117
116
  version: '0'
118
- type: :development
117
+ name: rubocop
119
118
  prerelease: false
119
+ type: :development
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - ">="
@@ -131,6 +131,7 @@ executables:
131
131
  extensions: []
132
132
  extra_rdoc_files: []
133
133
  files:
134
+ - ".github/workflows/release.yml"
134
135
  - ".gitignore"
135
136
  - ".rspec"
136
137
  - ".rubocop.yml"
@@ -147,6 +148,7 @@ files:
147
148
  - bin/console.sh
148
149
  - bin/setup.sh
149
150
  - cluster_config.yaml.example
151
+ - config/warble.rb
150
152
  - entrypoint.sh
151
153
  - exe/hetzner-k3s
152
154
  - hetzner-k3s.gemspec
@@ -178,16 +180,16 @@ require_paths:
178
180
  - lib
179
181
  required_ruby_version: !ruby/object:Gem::Requirement
180
182
  requirements:
181
- - - ">="
183
+ - - "~>"
182
184
  - !ruby/object:Gem::Version
183
- version: 3.1.2
185
+ version: 2.7.1
184
186
  required_rubygems_version: !ruby/object:Gem::Requirement
185
187
  requirements:
186
- - - ">="
188
+ - - ">"
187
189
  - !ruby/object:Gem::Version
188
- version: '0'
190
+ version: 1.3.1
189
191
  requirements: []
190
- rubygems_version: 3.3.7
192
+ rubygems_version: 3.2.29
191
193
  signing_key:
192
194
  specification_version: 4
193
195
  summary: A CLI to create a Kubernetes cluster in Hetzner Cloud very quickly using