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 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
@@ -0,0 +1,2 @@
1
+ ## 0.1.0
2
+ * Birthday!
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development, :test do
6
+ gem 'pry-byebug'
7
+ gem 'rake'
8
+ end
9
+
10
+ group :test do
11
+ gem 'rspec', '~> 3.0'
12
+ end
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
@@ -0,0 +1,5 @@
1
+ module Kuby
2
+ module Kind
3
+ VERSION = '0.1.0'.freeze
4
+ end
5
+ end
data/lib/kuby/kind.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'kuby/kind/provider'
2
+
3
+ module Kuby
4
+ module Kind
5
+ autoload :Config, 'kuby/kind/config'
6
+ end
7
+ end
8
+
9
+ Kuby.register_provider(:kind, ::Kuby::Kind::Provider)
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: []