kuby-kind 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/CHANGELOG.md +2 -0
- data/Gemfile +12 -0
- data/LICENSE +21 -0
- data/README.md +35 -0
- data/Rakefile +15 -0
- data/kuby-kind.gemspec +20 -0
- data/lib/kuby/kind/config.rb +19 -0
- data/lib/kuby/kind/provider.rb +212 -0
- data/lib/kuby/kind/version.rb +5 -0
- data/lib/kuby/kind.rb +9 -0
- metadata +86 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7b414415b8e0f72a7b264bbd3d1dfc06bd78206ff34226f07e880edfd11ff321
|
4
|
+
data.tar.gz: 603211fee0c7673e392aaff635a7efc2a87f90cc8108ec7d58fa078443b81870
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: de56877bbf471676c15efa6f70963ded9ca110fc702e9da5616ba53a0bb17e2db39109c7f74282d588e3982649a3488dc431e9331bddc4937052614252bc78ff
|
7
|
+
data.tar.gz: 25439df47e8cdcf4613f1cfe88f551f7b1371cea25aa570a09581219a4f9d589762648140701ef1cfea5ecff08ede97e51043c4eaf04d866bf9398dbe1e65e66
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2022 Cameron Dutro
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
## kuby-kind
|
2
|
+
|
3
|
+
Kind provider for [Kuby](https://github.com/getkuby/kuby-core).
|
4
|
+
|
5
|
+
## Intro
|
6
|
+
|
7
|
+
In Kuby parlance, a "provider" is an [adapter](https://en.wikipedia.org/wiki/Adapter_pattern) that enables Kuby to deploy apps to a specific cloud provider. In this case, we're talking about [Kind](https://kind.sigs.k8s.io/), which is a tool that makes it easy to run local, ephemeral Kubernetes clusters.
|
8
|
+
|
9
|
+
All providers adhere to a specific interface, meaning you can swap out one provider for another without having to change your code.
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
Enable the Kind provider like so:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
Kuby.define('MyApp') do
|
17
|
+
environment(:production) do
|
18
|
+
kubernetes do
|
19
|
+
|
20
|
+
provider :kind
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
Once configured, you should be able to run all the Kuby commands as you would with any provider.
|
28
|
+
|
29
|
+
## License
|
30
|
+
|
31
|
+
Licensed under the MIT license. See LICENSE for details.
|
32
|
+
|
33
|
+
## Authors
|
34
|
+
|
35
|
+
* Cameron C. Dutro: http://github.com/camertron
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'rubygems/package_task'
|
4
|
+
|
5
|
+
require 'kuby/kind'
|
6
|
+
require 'pry-byebug'
|
7
|
+
|
8
|
+
Bundler::GemHelper.install_tasks
|
9
|
+
|
10
|
+
task default: :spec
|
11
|
+
|
12
|
+
desc 'Run specs'
|
13
|
+
RSpec::Core::RakeTask.new do |t|
|
14
|
+
t.pattern = './spec/**/*_spec.rb'
|
15
|
+
end
|
data/kuby-kind.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
2
|
+
require 'kuby/kind/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'kuby-kind'
|
6
|
+
s.version = ::Kuby::Kind::VERSION
|
7
|
+
s.authors = ['Cameron Dutro']
|
8
|
+
s.email = ['camertron@gmail.com']
|
9
|
+
s.homepage = 'http://github.com/getkuby/kuby-kind'
|
10
|
+
|
11
|
+
s.description = s.summary = 'Kind provider for Kuby.'
|
12
|
+
|
13
|
+
s.platform = Gem::Platform::RUBY
|
14
|
+
|
15
|
+
s.add_dependency 'kuby-core', '>= 0.16.0', '< 1.0'
|
16
|
+
s.add_dependency 'kind-rb', '~> 0.1'
|
17
|
+
|
18
|
+
s.require_path = 'lib'
|
19
|
+
s.files = Dir['{lib,spec}/**/*', 'Gemfile', 'LICENSE', 'CHANGELOG.md', 'README.md', 'Rakefile', 'kuby-kind.gemspec']
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Kuby
|
2
|
+
module Kind
|
3
|
+
class Config
|
4
|
+
attr_reader :exposed_ports
|
5
|
+
|
6
|
+
def initialize(&block)
|
7
|
+
@exposed_ports = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def expose_port(port)
|
11
|
+
@exposed_ports << port
|
12
|
+
end
|
13
|
+
|
14
|
+
def hide_port(port)
|
15
|
+
@exposed_ports.delete(port)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,212 @@
|
|
1
|
+
require 'kuby'
|
2
|
+
require 'kind-rb'
|
3
|
+
require 'open3'
|
4
|
+
|
5
|
+
module Kuby
|
6
|
+
module Kind
|
7
|
+
class Provider < ::Kuby::Kubernetes::Provider
|
8
|
+
STORAGE_CLASS_NAME = 'default'.freeze
|
9
|
+
DEFAULT_EXPOSED_PORTS = [80, 443].freeze
|
10
|
+
|
11
|
+
attr_reader :config
|
12
|
+
|
13
|
+
def configure(&block)
|
14
|
+
config.instance_eval(&block) if block
|
15
|
+
end
|
16
|
+
|
17
|
+
def kubeconfig_path
|
18
|
+
File.join(
|
19
|
+
kubeconfig_dir, "#{cluster_name}-kubeconfig.yaml"
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def storage_class_name
|
24
|
+
STORAGE_CLASS_NAME
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup
|
28
|
+
@setting_up = true
|
29
|
+
ensure_cluster!
|
30
|
+
end
|
31
|
+
|
32
|
+
def before_deploy(*)
|
33
|
+
ensure_cluster!
|
34
|
+
load_images
|
35
|
+
end
|
36
|
+
|
37
|
+
def after_configuration
|
38
|
+
if nginx_ingress = environment.kubernetes.plugin(:nginx_ingress)
|
39
|
+
nginx_ingress.configure do
|
40
|
+
provider('kind') unless provider
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def after_initialize
|
48
|
+
@already_ensured = false
|
49
|
+
@config = Config.new
|
50
|
+
|
51
|
+
configure do
|
52
|
+
DEFAULT_EXPOSED_PORTS.each do |port|
|
53
|
+
expose_port port
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
kubernetes_cli.before_execute do
|
58
|
+
ensure_cluster!
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def load_images
|
63
|
+
Kuby.logger.info("Loading Docker images into Kind cluster...")
|
64
|
+
|
65
|
+
environment.kubernetes.docker_images.each do |image|
|
66
|
+
image = image.current_version
|
67
|
+
|
68
|
+
# Only load the main tag because it's so darn expensive to load large
|
69
|
+
# images into Kind clusters. Kind doesn't seem to realize images with
|
70
|
+
# the same SHA but different tags are the same, :eyeroll:
|
71
|
+
cmd = [
|
72
|
+
KindRb.executable,
|
73
|
+
'load', 'docker-image', "#{image.image_url}:#{image.main_tag}",
|
74
|
+
'--name', cluster_name
|
75
|
+
]
|
76
|
+
|
77
|
+
system(cmd.join(' '))
|
78
|
+
end
|
79
|
+
|
80
|
+
Kuby.logger.info("Docker images loaded into Kind cluster successfully.")
|
81
|
+
end
|
82
|
+
|
83
|
+
def ensure_cluster!
|
84
|
+
return if @already_ensured
|
85
|
+
|
86
|
+
if !cluster_defined? || !cluster_running? || !cluster_reachable?
|
87
|
+
recreate_cluster!
|
88
|
+
|
89
|
+
unless @setting_up
|
90
|
+
Kuby.logger.info("Local Kind cluster (re)created, please run `kuby setup`.")
|
91
|
+
exit 0
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
@already_ensured = true
|
96
|
+
end
|
97
|
+
|
98
|
+
def recreate_cluster!
|
99
|
+
delete_cluster! if cluster_running?
|
100
|
+
create_cluster!
|
101
|
+
end
|
102
|
+
|
103
|
+
def delete_cluster!
|
104
|
+
cmd = [
|
105
|
+
KindRb.executable, 'delete', 'cluster',
|
106
|
+
'--name', cluster_name,
|
107
|
+
'--kubeconfig', kubeconfig_path
|
108
|
+
]
|
109
|
+
|
110
|
+
system(cmd.join(' '))
|
111
|
+
|
112
|
+
if $?.exitstatus != 0
|
113
|
+
raise 'Kind command failed'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def create_cluster!
|
118
|
+
cmd = [
|
119
|
+
KindRb.executable, 'create', 'cluster',
|
120
|
+
'--name', cluster_name,
|
121
|
+
'--kubeconfig', kubeconfig_path,
|
122
|
+
]
|
123
|
+
|
124
|
+
if (cluster_config = make_cluster_config)
|
125
|
+
cmd << '--config -'
|
126
|
+
|
127
|
+
Open3.pipeline_w(cmd.join(' ')) do |stdin, wait_threads|
|
128
|
+
stdin.puts(YAML.dump(cluster_config))
|
129
|
+
stdin.close
|
130
|
+
wait_threads.each(&:join)
|
131
|
+
|
132
|
+
if wait_threads.first.value.exitstatus != 0
|
133
|
+
raise 'Kind command failed'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
else
|
137
|
+
system(cmd.join(' '))
|
138
|
+
|
139
|
+
if $?.exitstatus != 0
|
140
|
+
raise 'Kind command failed'
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def make_cluster_config
|
146
|
+
return nil if config.exposed_ports.empty?
|
147
|
+
|
148
|
+
{
|
149
|
+
'kind' => 'Cluster',
|
150
|
+
'apiVersion' => 'kind.x-k8s.io/v1alpha4',
|
151
|
+
'nodes' => [{
|
152
|
+
'role' => 'control-plane',
|
153
|
+
'kubeadmConfigPatches' => [
|
154
|
+
<<~END,
|
155
|
+
kind: InitConfiguration
|
156
|
+
nodeRegistration:
|
157
|
+
kubeletExtraArgs:
|
158
|
+
node-labels: "ingress-ready=true"
|
159
|
+
END
|
160
|
+
],
|
161
|
+
'extraPortMappings' => config.exposed_ports.map do |port|
|
162
|
+
{ 'containerPort' => port, 'hostPort' => port, 'protocol' => 'TCP' }
|
163
|
+
end
|
164
|
+
}]
|
165
|
+
}
|
166
|
+
end
|
167
|
+
|
168
|
+
def cluster_defined?
|
169
|
+
return false if !File.exist?(kubeconfig_path)
|
170
|
+
|
171
|
+
kubeconfig = YAML.load_file(kubeconfig_path)
|
172
|
+
cluster_config = (kubeconfig['clusters'] || []).find do |cluster|
|
173
|
+
cluster['name'] == context
|
174
|
+
end
|
175
|
+
|
176
|
+
!!cluster_config
|
177
|
+
end
|
178
|
+
|
179
|
+
def cluster_running?
|
180
|
+
cmd = [KindRb.executable, 'get', 'clusters']
|
181
|
+
cluster_names = `#{cmd.join(' ')}`.strip.split("\n")
|
182
|
+
cluster_names.include?(cluster_name)
|
183
|
+
end
|
184
|
+
|
185
|
+
def cluster_reachable?
|
186
|
+
cmd = [
|
187
|
+
kubernetes_cli.executable,
|
188
|
+
'--kubeconfig', kubeconfig_path,
|
189
|
+
'--context', context,
|
190
|
+
'get', 'ns'
|
191
|
+
]
|
192
|
+
|
193
|
+
`#{cmd.join(' ')}`
|
194
|
+
$?.success?
|
195
|
+
end
|
196
|
+
|
197
|
+
def cluster_name
|
198
|
+
@cluster_name ||= environment.app_name.downcase
|
199
|
+
end
|
200
|
+
|
201
|
+
def context
|
202
|
+
@context ||= "kind-#{cluster_name}"
|
203
|
+
end
|
204
|
+
|
205
|
+
def kubeconfig_dir
|
206
|
+
@kubeconfig_dir ||= File.join(
|
207
|
+
Dir.tmpdir, 'kuby-kind'
|
208
|
+
)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
data/lib/kuby/kind.rb
ADDED
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kuby-kind
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cameron Dutro
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-02-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: kuby-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.16.0
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '1.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.16.0
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: kind-rb
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.1'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0.1'
|
47
|
+
description: Kind provider for Kuby.
|
48
|
+
email:
|
49
|
+
- camertron@gmail.com
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- CHANGELOG.md
|
55
|
+
- Gemfile
|
56
|
+
- LICENSE
|
57
|
+
- README.md
|
58
|
+
- Rakefile
|
59
|
+
- kuby-kind.gemspec
|
60
|
+
- lib/kuby/kind.rb
|
61
|
+
- lib/kuby/kind/config.rb
|
62
|
+
- lib/kuby/kind/provider.rb
|
63
|
+
- lib/kuby/kind/version.rb
|
64
|
+
homepage: http://github.com/getkuby/kuby-kind
|
65
|
+
licenses: []
|
66
|
+
metadata: {}
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
requirements: []
|
82
|
+
rubygems_version: 3.2.22
|
83
|
+
signing_key:
|
84
|
+
specification_version: 4
|
85
|
+
summary: Kind provider for Kuby.
|
86
|
+
test_files: []
|