kube-deploy 0.1.0 → 0.2.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 +4 -4
- data/.gitignore +2 -0
- data/.rubocop-http---shopify-github-io-ruby-style-guide-rubocop-yml +1140 -0
- data/.rubocop.yml +6 -0
- data/Gemfile.lock +78 -2
- data/Rakefile +9 -1
- data/bin/console +1 -1
- data/bin/kube-deploy +10 -0
- data/exe/kube-deploy +2 -1
- data/kube-deploy.gemspec +10 -2
- data/kube.deploy +14 -0
- data/lib/helpers/printer.rb +132 -0
- data/lib/helpers/shell_runner.rb +17 -0
- data/lib/kube-deploy.rb +73 -0
- data/lib/kube-deploy/docker_hub.rb +29 -0
- data/lib/{version.rb → kube-deploy/version.rb} +1 -1
- data/test-2.yaml +5 -0
- data/test.yml +5 -0
- metadata +127 -5
- data/lib/kube_deploy.rb +0 -6
data/.rubocop.yml
ADDED
data/Gemfile.lock
CHANGED
|
@@ -1,22 +1,98 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
kube-deploy (0.
|
|
4
|
+
kube-deploy (0.2.0)
|
|
5
|
+
kubeclient
|
|
5
6
|
thor
|
|
6
7
|
|
|
7
8
|
GEM
|
|
8
9
|
remote: https://rubygems.org/
|
|
9
10
|
specs:
|
|
11
|
+
addressable (2.5.0)
|
|
12
|
+
public_suffix (~> 2.0, >= 2.0.2)
|
|
13
|
+
ansi (1.5.0)
|
|
14
|
+
ast (2.3.0)
|
|
15
|
+
builder (3.2.3)
|
|
16
|
+
byebug (9.0.6)
|
|
17
|
+
coderay (1.1.1)
|
|
18
|
+
crack (0.4.3)
|
|
19
|
+
safe_yaml (~> 1.0.0)
|
|
20
|
+
domain_name (0.5.20170223)
|
|
21
|
+
unf (>= 0.0.5, < 1.0.0)
|
|
22
|
+
hashdiff (0.3.2)
|
|
23
|
+
http (0.9.8)
|
|
24
|
+
addressable (~> 2.3)
|
|
25
|
+
http-cookie (~> 1.0)
|
|
26
|
+
http-form_data (~> 1.0.1)
|
|
27
|
+
http_parser.rb (~> 0.6.0)
|
|
28
|
+
http-cookie (1.0.3)
|
|
29
|
+
domain_name (~> 0.5)
|
|
30
|
+
http-form_data (1.0.1)
|
|
31
|
+
http_parser.rb (0.6.0)
|
|
32
|
+
kubeclient (2.3.0)
|
|
33
|
+
http (= 0.9.8)
|
|
34
|
+
recursive-open-struct (= 1.0.0)
|
|
35
|
+
rest-client
|
|
36
|
+
method_source (0.8.2)
|
|
37
|
+
mime-types (3.1)
|
|
38
|
+
mime-types-data (~> 3.2015)
|
|
39
|
+
mime-types-data (3.2016.0521)
|
|
40
|
+
minitest (5.10.1)
|
|
41
|
+
minitest-reporters (1.1.14)
|
|
42
|
+
ansi
|
|
43
|
+
builder
|
|
44
|
+
minitest (>= 5.0)
|
|
45
|
+
ruby-progressbar
|
|
46
|
+
netrc (0.11.0)
|
|
47
|
+
parser (2.4.0.0)
|
|
48
|
+
ast (~> 2.2)
|
|
49
|
+
powerpack (0.1.1)
|
|
50
|
+
pry (0.10.4)
|
|
51
|
+
coderay (~> 1.1.0)
|
|
52
|
+
method_source (~> 0.8.1)
|
|
53
|
+
slop (~> 3.4)
|
|
54
|
+
public_suffix (2.0.5)
|
|
55
|
+
rainbow (2.2.1)
|
|
10
56
|
rake (10.5.0)
|
|
57
|
+
recursive-open-struct (1.0.0)
|
|
58
|
+
rest-client (2.0.1)
|
|
59
|
+
http-cookie (>= 1.0.2, < 2.0)
|
|
60
|
+
mime-types (>= 1.16, < 4.0)
|
|
61
|
+
netrc (~> 0.8)
|
|
62
|
+
rubocop (0.48.0)
|
|
63
|
+
parser (>= 2.3.3.1, < 3.0)
|
|
64
|
+
powerpack (~> 0.1)
|
|
65
|
+
rainbow (>= 1.99.1, < 3.0)
|
|
66
|
+
ruby-progressbar (~> 1.7)
|
|
67
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
|
68
|
+
ruby-progressbar (1.8.1)
|
|
69
|
+
safe_yaml (1.0.4)
|
|
70
|
+
slop (3.6.0)
|
|
11
71
|
thor (0.19.4)
|
|
72
|
+
unf (0.1.4)
|
|
73
|
+
unf_ext
|
|
74
|
+
unf_ext (0.0.7.2)
|
|
75
|
+
unicode-display_width (1.1.3)
|
|
76
|
+
vcr (3.0.3)
|
|
77
|
+
webmock (2.3.2)
|
|
78
|
+
addressable (>= 2.3.6)
|
|
79
|
+
crack (>= 0.3.2)
|
|
80
|
+
hashdiff
|
|
12
81
|
|
|
13
82
|
PLATFORMS
|
|
14
83
|
ruby
|
|
15
84
|
|
|
16
85
|
DEPENDENCIES
|
|
17
86
|
bundler (~> 1.14)
|
|
87
|
+
byebug
|
|
18
88
|
kube-deploy!
|
|
89
|
+
minitest (~> 5.0)
|
|
90
|
+
minitest-reporters
|
|
91
|
+
pry
|
|
19
92
|
rake (~> 10.0)
|
|
93
|
+
rubocop
|
|
94
|
+
vcr
|
|
95
|
+
webmock
|
|
20
96
|
|
|
21
97
|
BUNDLED WITH
|
|
22
|
-
1.
|
|
98
|
+
1.15.0
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
data/bin/kube-deploy
ADDED
data/exe/kube-deploy
CHANGED
data/kube-deploy.gemspec
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
-
require 'version'
|
|
4
|
+
require 'kube-deploy/version'
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = "kube-deploy"
|
|
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
|
9
9
|
spec.authors = ["Benjamin Caldwell"]
|
|
10
10
|
spec.email = ["caldwellbenjamin8@gmail.com"]
|
|
11
11
|
|
|
12
|
-
spec.summary =
|
|
12
|
+
spec.summary = 'A tool deploy folders to a kubernetes cluster'
|
|
13
13
|
spec.homepage = "https://github.com/benjamincaldwell/kube-deploy"
|
|
14
14
|
spec.license = "MIT"
|
|
15
15
|
|
|
@@ -22,6 +22,14 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
|
|
23
23
|
spec.add_development_dependency "bundler", "~> 1.14"
|
|
24
24
|
spec.add_development_dependency "rake", "~> 10.0"
|
|
25
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
|
26
|
+
spec.add_development_dependency "minitest-reporters"
|
|
27
|
+
spec.add_development_dependency "pry"
|
|
28
|
+
spec.add_development_dependency "byebug"
|
|
29
|
+
spec.add_development_dependency "rubocop"
|
|
30
|
+
spec.add_development_dependency "vcr"
|
|
31
|
+
spec.add_development_dependency "webmock"
|
|
25
32
|
|
|
26
33
|
spec.add_dependency "thor"
|
|
34
|
+
spec.add_dependency "kubeclient"
|
|
27
35
|
end
|
data/kube.deploy
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require 'io/console'
|
|
3
|
+
|
|
4
|
+
class Printer
|
|
5
|
+
####################
|
|
6
|
+
#
|
|
7
|
+
# Logging
|
|
8
|
+
#
|
|
9
|
+
####################
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
def put_header(text, color = "\x1b[36m")
|
|
13
|
+
put_edge(color, "┏━━ ", text)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def put_edge(color, prefix, text)
|
|
17
|
+
ptext = "#{color}#{prefix}#{text}"
|
|
18
|
+
textwidth = printing_width(ptext)
|
|
19
|
+
|
|
20
|
+
console = IO.console
|
|
21
|
+
termwidth = console ? console.winsize[1] : 80
|
|
22
|
+
termwidth = 30 if termwidth < 30
|
|
23
|
+
|
|
24
|
+
if textwidth > termwidth
|
|
25
|
+
ptext = ptext[0...termwidth]
|
|
26
|
+
textwidth = termwidth
|
|
27
|
+
end
|
|
28
|
+
padwidth = termwidth - textwidth
|
|
29
|
+
pad = "━" * padwidth
|
|
30
|
+
formatted = "#{ptext}#{color}#{pad}\x1b[0m\n"
|
|
31
|
+
|
|
32
|
+
puts formatted
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def log(msg)
|
|
36
|
+
puts "\x1b[36m┃\x1b[0m " + msg
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# ANSI escape sequences (like \x1b[31m) have zero width.
|
|
40
|
+
# when calculating the padding width, we must exclude them.
|
|
41
|
+
def printing_width(str)
|
|
42
|
+
str.gsub(/\x1b\[[\d;]+[A-z]/, '').size
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def put_footer(success = true, success_color = "\x1b[36m")
|
|
46
|
+
if success
|
|
47
|
+
put_edge(success_color, "┗", "")
|
|
48
|
+
else
|
|
49
|
+
text = "💥 Failed! Aborting! "
|
|
50
|
+
put_edge("\x1b[31m", "┗━━ ", text)
|
|
51
|
+
exit
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def prompt_user_with_options(question, options)
|
|
56
|
+
require 'readline'
|
|
57
|
+
|
|
58
|
+
log(question)
|
|
59
|
+
log("Your options are:")
|
|
60
|
+
options.each_with_index do |v, idx|
|
|
61
|
+
log("#{idx + 1}) #{v}")
|
|
62
|
+
end
|
|
63
|
+
log("Choose a number between 1 and #{options.length}")
|
|
64
|
+
|
|
65
|
+
Readline.completion_append_character = " "
|
|
66
|
+
Readline.completion_proc = nil
|
|
67
|
+
|
|
68
|
+
buf = -1
|
|
69
|
+
available = (1..options.length).to_a
|
|
70
|
+
until available.include?(buf.to_i)
|
|
71
|
+
begin
|
|
72
|
+
buf = Readline.readline("\x1b[34m┃ > \x1b[33m", true)
|
|
73
|
+
rescue Interrupt
|
|
74
|
+
nil
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
if buf.nil?
|
|
78
|
+
STDERR.puts
|
|
79
|
+
next
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
buf = buf.chomp
|
|
83
|
+
buf = -1 if buf.empty?
|
|
84
|
+
buf = -1 if buf.to_i.to_s != buf
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
options[buf.to_i - 1]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def puts_coloured(a, error: false)
|
|
91
|
+
text = a
|
|
92
|
+
.gsub(/{{green:(.*?)}}/, "\x1b[32m\\1\x1b[0m")
|
|
93
|
+
.gsub(/{{bold:(.*?)}}/, "\x1b[1m\\1\x1b[0m")
|
|
94
|
+
.gsub(/{{cyan:(.*?)}}/, "\x1b[36m\\1\x1b[0m")
|
|
95
|
+
.gsub(/{{red:(.*?)}}/, "\x1b[31m\\1\x1b[0m")
|
|
96
|
+
|
|
97
|
+
if error
|
|
98
|
+
puts_red text
|
|
99
|
+
else
|
|
100
|
+
puts text
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def puts_info(a, mark = '?')
|
|
105
|
+
puts_blue("\x1b[34m#{mark} \x1b[0m" + a)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def puts_success(a)
|
|
109
|
+
puts_green("\x1b[32m✓\x1b[0m " + a)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def puts_failure(a)
|
|
113
|
+
puts_red("\x1b[31m✗\x1b[0m " + a)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def puts_blue(a)
|
|
117
|
+
puts_raw("\x1b[34m┃\x1b[0m " + a)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def puts_green(a)
|
|
121
|
+
puts_raw("\x1b[32m┃\x1b[0m " + a)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def puts_red(a)
|
|
125
|
+
puts_raw("\x1b[31m┃\x1b[0m " + a)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def puts_raw(a)
|
|
129
|
+
STDOUT.puts(a)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module ShellRunner
|
|
2
|
+
def self.run(title, commands)
|
|
3
|
+
return unless commands&.any?
|
|
4
|
+
Printer.put_header(title)
|
|
5
|
+
successful = true
|
|
6
|
+
commands.each do |command|
|
|
7
|
+
system(command)
|
|
8
|
+
if $?.exitstatus != 0
|
|
9
|
+
successful = false
|
|
10
|
+
Printer.puts_failure("#{command} returned non-zero status code: #{$?.exitstatus}")
|
|
11
|
+
break
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
Printer.put_footer(successful)
|
|
15
|
+
exit 1 unless successful
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/kube-deploy.rb
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require 'thor'
|
|
2
|
+
require 'yaml'
|
|
3
|
+
|
|
4
|
+
require 'helpers/printer'
|
|
5
|
+
require 'helpers/shell_runner'
|
|
6
|
+
|
|
7
|
+
require 'byebug'
|
|
8
|
+
|
|
9
|
+
module KubeDeploy
|
|
10
|
+
class CLI < Thor
|
|
11
|
+
desc "apply", "deploys configs from current folder to kubernetes cluster"
|
|
12
|
+
method_option :config, :type => :string, :aliases => "-f"
|
|
13
|
+
def apply
|
|
14
|
+
pwd = Dir.pwd
|
|
15
|
+
config = if options.config?
|
|
16
|
+
config_file = File.join(pwd, options.config)
|
|
17
|
+
unless File.exist? config_file
|
|
18
|
+
Printer.puts_failure("#{options.config} does not exist")
|
|
19
|
+
exit 1
|
|
20
|
+
end
|
|
21
|
+
begin
|
|
22
|
+
YAML::load_file(config_file)
|
|
23
|
+
rescue Exception => e
|
|
24
|
+
Printer.puts_failure("Unable to parse #{config}: #{e.message}")
|
|
25
|
+
end
|
|
26
|
+
else
|
|
27
|
+
{
|
|
28
|
+
"apply" => {
|
|
29
|
+
"1" => Dir["*.yaml"] + Dir["*.yml"]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
ShellRunner.run "Running pre script", config["pre-script"]
|
|
35
|
+
|
|
36
|
+
config["apply"].each do |stage, files|
|
|
37
|
+
Printer.put_header("Applying stage #{stage}")
|
|
38
|
+
|
|
39
|
+
successful = true
|
|
40
|
+
extensions = %w(.yml .yaml).unshift("")
|
|
41
|
+
|
|
42
|
+
files.each do |file|
|
|
43
|
+
break unless successful
|
|
44
|
+
|
|
45
|
+
extensions.each do |extension|
|
|
46
|
+
config_file = File.join(pwd, file) + "#{extension}"
|
|
47
|
+
next unless File.exist? config_file
|
|
48
|
+
basename = File.basename(config_file)
|
|
49
|
+
unless system("kubectl", "apply", "-f", config_file)
|
|
50
|
+
puts "\x1b[31m✗\x1b[0m Failed to apply #{basename}"
|
|
51
|
+
successful = false
|
|
52
|
+
break
|
|
53
|
+
end
|
|
54
|
+
puts "\x1b[32m✓\x1b[0m Applied #{basename}"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
Printer.put_footer(successful)
|
|
58
|
+
exit 1 unless successful
|
|
59
|
+
|
|
60
|
+
ShellRunner.run "Running post stage script (#{stage})", config["post-stage"]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
ShellRunner.run "Running post script", config["post-script"]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
desc "version", "displays installed version"
|
|
67
|
+
def version
|
|
68
|
+
puts KubeDeploy::VERSION
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
default_task :apply
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# https://success.docker.com/Cloud/Solve/How_do_I_authenticate_with_the_V2_API%3F
|
|
2
|
+
require 'net/http'
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module KubeDeploy
|
|
6
|
+
module Docker
|
|
7
|
+
class Hub
|
|
8
|
+
# def initialize(username = nil, password = nil)
|
|
9
|
+
# @username = username
|
|
10
|
+
# @password = password
|
|
11
|
+
# end
|
|
12
|
+
def repository(namespace = "library", project)
|
|
13
|
+
api_request("repositories/#{namespace}/#{project}")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def api_request(path = "")
|
|
17
|
+
url = URI.join("https://hub.docker.com/v2/", path)
|
|
18
|
+
req = Net::HTTP::Get.new(url)
|
|
19
|
+
# # req["Content-Type"] = "application/json"
|
|
20
|
+
res = Net::HTTP.start(url.hostname, url.port, use_ssl: true) do |http|
|
|
21
|
+
http.request(req)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
return nil unless res.code == "200"
|
|
25
|
+
JSON.parse(res.body)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|