hetzner-k3s 0.5.9 → 0.6.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 65fe7fa7e6bdeeb49175cfb92184ab320ef8ac40a3aa03f921f1e5fda1b172d7
4
- data.tar.gz: 1448919374ef90f7614580251b28000c470b0ed7fba39724e8953f29f176c1bb
3
+ metadata.gz: 4d8a90e68ae6fb3b434fb4f65ed00a9508fa405d5d8cf87c8cc45e86c655ec56
4
+ data.tar.gz: f35647f4e10202a483aa73b79d9c4d7728904978d72943cd7f51ccdb8ff739fe
5
5
  SHA512:
6
- metadata.gz: 15f783adb7408a1df5c3e9a114d9dcbc61830ead33acb7bc162ca935b6cdcfe26507e2c404d48c831cae600fe765adc31e686b511c4f675c561d6eb9acabafd2
7
- data.tar.gz: df10039025e735d6a73c84fb60516d70bc0aa48220db1bab9d99dd30caad87339ba6be83e2d3f1029f40f95719a6fcde5784956c86ef20d524b67d504f93920a
6
+ metadata.gz: 41ecc26d3b5aaa22b363ff425ef7d0d47a3510aecdc8a8389fd16d2889a77ce278152a20a885a1ba460b19bc07224e1a61c6d3cb8e9f0ee554692f90564a8553
7
+ data.tar.gz: 37860df2822b9316876814bb8a33df5fbbc087f3c21ef53faf8be35ec56cfbd584bc62db1d1f98558e32d75985fe6d6e0836934838b23d0bb89ffc135a336d08
@@ -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 ./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.rc1'
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.rc1
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