minfra-cli 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.dockerignore +12 -0
- data/.gitignore +16 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +2 -0
- data/Dockerfile +12 -0
- data/bin/build +20 -0
- data/bin/console +16 -0
- data/bin/container_exec +9 -0
- data/bin/run_tests +74 -0
- data/bin/setup.sh +22 -0
- data/exe/minfra +6 -0
- data/lib/deep_merge.rb +149 -0
- data/lib/hash.rb +28 -0
- data/lib/minfra/cli/ask.rb +43 -0
- data/lib/minfra/cli/command.rb +35 -0
- data/lib/minfra/cli/commands/dev.rb +54 -0
- data/lib/minfra/cli/commands/kube.rb +279 -0
- data/lib/minfra/cli/commands/project/branch.rb +17 -0
- data/lib/minfra/cli/commands/project/tag.rb +40 -0
- data/lib/minfra/cli/commands/project.rb +113 -0
- data/lib/minfra/cli/commands/setup.rb +49 -0
- data/lib/minfra/cli/commands/stack/app_template.rb +65 -0
- data/lib/minfra/cli/commands/stack/client_template.rb +36 -0
- data/lib/minfra/cli/commands/stack/kube_stack_template.rb +94 -0
- data/lib/minfra/cli/commands/stack.rb +120 -0
- data/lib/minfra/cli/commands/tag.rb +86 -0
- data/lib/minfra/cli/common.rb +41 -0
- data/lib/minfra/cli/config.rb +111 -0
- data/lib/minfra/cli/document.rb +19 -0
- data/lib/minfra/cli/hook.rb +65 -0
- data/lib/minfra/cli/logging.rb +26 -0
- data/lib/minfra/cli/main_command.rb +32 -0
- data/lib/minfra/cli/plugins.rb +34 -0
- data/lib/minfra/cli/runner.rb +59 -0
- data/lib/minfra/cli/templater.rb +63 -0
- data/lib/minfra/cli/version.rb +5 -0
- data/lib/minfra/cli.rb +80 -0
- data/lib/orchparty/ast.rb +53 -0
- data/lib/orchparty/cli.rb +69 -0
- data/lib/orchparty/context.rb +22 -0
- data/lib/orchparty/dsl_parser.rb +229 -0
- data/lib/orchparty/dsl_parser_kubernetes.rb +361 -0
- data/lib/orchparty/kubernetes_application.rb +305 -0
- data/lib/orchparty/plugin.rb +24 -0
- data/lib/orchparty/plugins/env.rb +41 -0
- data/lib/orchparty/transformations/all.rb +18 -0
- data/lib/orchparty/transformations/mixin.rb +73 -0
- data/lib/orchparty/transformations/remove_internal.rb +16 -0
- data/lib/orchparty/transformations/sort.rb +10 -0
- data/lib/orchparty/transformations/variable.rb +56 -0
- data/lib/orchparty/transformations.rb +24 -0
- data/lib/orchparty/version.rb +3 -0
- data/lib/orchparty.rb +59 -0
- data/minfra-cli.gemspec +40 -0
- data/project.json +7 -0
- data/templates/kind.yaml.erb +33 -0
- data/templates/kube_config.yaml.erb +7 -0
- data/templates/minfra_config.json.erb +26 -0
- metadata +196 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fdef57265500c1ab2f82470de61a21d1d604d4cdbc198f2acbcafdab9cb37548
|
4
|
+
data.tar.gz: f7a25a0c65239ccaa49331a0e94d14494b92a44927df112c2258d6b42ef51420
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e2875bcf474cbed4017f6fb5e7188745b04357e0181a9ab1d8641d041d880e3152624e21f4fed4317a9c4a24c1c1e3d00c552f4fcaf558324a78d74d08de8930
|
7
|
+
data.tar.gz: f6ae3c0c3a82ca453a886a8d1bfc6ea2170a967f42094a482d769cbb40f60706416f2592465202afc2e04f7bd957068730d8da1420b14b6c13c331864770e1ca
|
data/.dockerignore
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
data/CHANGELOG.md
ADDED
data/Dockerfile
ADDED
data/bin/build
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
set -e
|
3
|
+
|
4
|
+
app_dir=`pwd`
|
5
|
+
prj_file="$app_dir/project.json"
|
6
|
+
|
7
|
+
repo=`jq -r ".docker.repo" "$prj_file"`
|
8
|
+
project=`jq -r ".docker.name" "$prj_file"`
|
9
|
+
path=`jq -r ".path" "$prj_file"`
|
10
|
+
|
11
|
+
ACTION=${1:-local}
|
12
|
+
|
13
|
+
case "$ACTION" in
|
14
|
+
"local" )
|
15
|
+
docker build -t $repo/$project:latest $app_dir
|
16
|
+
;;
|
17
|
+
* )
|
18
|
+
echo "unknown action: '$ACTION'"
|
19
|
+
;;
|
20
|
+
esac
|
data/bin/console
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH << File.expand_path('../lib', __dir__)
|
4
|
+
|
5
|
+
require "bundler/setup"
|
6
|
+
require "minfra/cli"
|
7
|
+
|
8
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
9
|
+
# with your gem easier. You can also use a different console, if you like.
|
10
|
+
|
11
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
12
|
+
# require "pry"
|
13
|
+
# Pry.start
|
14
|
+
|
15
|
+
require "irb"
|
16
|
+
IRB.start
|
data/bin/container_exec
ADDED
data/bin/run_tests
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'erb'
|
3
|
+
require 'json'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
root=Pathname.new(File.expand_path('..', __dir__))
|
7
|
+
project_info=JSON.parse(File.read(root.join('project.json')))
|
8
|
+
|
9
|
+
def pull_base_image
|
10
|
+
dockerfile = File.read(File.expand_path('../Dockerfile', __dir__))
|
11
|
+
base_image = dockerfile.match(/^FROM .+$/).to_s.gsub(/^FROM /, '')
|
12
|
+
run("docker pull #{base_image}")
|
13
|
+
end
|
14
|
+
|
15
|
+
def run(command, exit_on_error=true)
|
16
|
+
puts "running: #{command}"
|
17
|
+
system(command, out: $stdout, err: :out)
|
18
|
+
exit_status=$?.exitstatus
|
19
|
+
if exit_status.nonzero? && exit_on_error
|
20
|
+
exit(exit_status)
|
21
|
+
end
|
22
|
+
exit_status
|
23
|
+
end
|
24
|
+
|
25
|
+
if ENV["INSIDE_CONTAINER"] == "true" then
|
26
|
+
puts 'setting up test and running rspec'
|
27
|
+
run("bundle exec rspec --colour --tty #{ARGV.join(' ')}")
|
28
|
+
exit(0)
|
29
|
+
end
|
30
|
+
|
31
|
+
def pull_base_image
|
32
|
+
dockerfile = File.read(File.expand_path('../Dockerfile', __dir__))
|
33
|
+
base_image = dockerfile.match(/^FROM .+$/).to_s.gsub(/^FROM /, '')
|
34
|
+
run("docker pull #{base_image}")
|
35
|
+
end
|
36
|
+
|
37
|
+
# We always pull the latest base image, to ensure that we don't build with
|
38
|
+
# an old base image that is already present on the Jenkins worker.
|
39
|
+
pull_base_image
|
40
|
+
|
41
|
+
@project_name = project_info["docker"]["name"] # used in docker-compose.yml
|
42
|
+
|
43
|
+
build_tag= ENV["BUILD_NUMBER"] || Time.now.strftime("%Y%m%d%H%M")
|
44
|
+
|
45
|
+
cache_tag_code = "git describe --abbrev=0 --tags `git rev-list HEAD --skip=1 --max-count=1 2>/dev/null` 2>/dev/null"
|
46
|
+
cache_tag = `#{cache_tag_code}`
|
47
|
+
|
48
|
+
unless $?.exitstatus == 0
|
49
|
+
puts ("getting cache tag failed, fallback to 'latest'")
|
50
|
+
cache_tag = "latest"
|
51
|
+
end
|
52
|
+
cache_tag = false unless ENV["BUILD_ID"]
|
53
|
+
|
54
|
+
volumes = []
|
55
|
+
|
56
|
+
volumes << "..:/code" unless ENV["BUILD_ID"]
|
57
|
+
|
58
|
+
@tag = build_tag
|
59
|
+
@cache_tag = nil #cache_tag
|
60
|
+
@volumes = volumes
|
61
|
+
|
62
|
+
# Run docker pull on cache
|
63
|
+
if @cache_tag
|
64
|
+
run("docker pull 858049876441.dkr.ecr.eu-west-1.amazonaws.com/#{@project_name}:#{@cache_tag}")
|
65
|
+
end
|
66
|
+
|
67
|
+
erb = ERB.new(File.open("#{__dir__}/../spec/docker-compose.yml").read, 0, '>')
|
68
|
+
File.write("#{__dir__}/../spec/docker-compose.run.yml", erb.result)
|
69
|
+
|
70
|
+
run("sudo docker-compose -f #{__dir__}/../spec/docker-compose.run.yml build")
|
71
|
+
envs=["-e 'INSIDE_CONTAINER=true'"]
|
72
|
+
exit_status=run("sudo docker-compose -f #{__dir__}/../spec/docker-compose.run.yml run --rm #{envs.join(' ')} tester bin/run_tests #{ARGV.join(' ')}", false)
|
73
|
+
run("sudo docker-compose -f #{__dir__}/../spec/docker-compose.run.yml down --remove-orphans") unless ENV["KEEP_SPEC_CONTAINERS"]
|
74
|
+
exit(exit_status)
|
data/bin/setup.sh
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
PROJ_NAME=$1
|
4
|
+
PROJ_PATH=`pwd`/$PROJ_NAME
|
5
|
+
|
6
|
+
echo "Setting up your project $PROJ_NAME"
|
7
|
+
|
8
|
+
mkdir $PROJ_NAME
|
9
|
+
|
10
|
+
mkdir $PROJ_NAME/stacks
|
11
|
+
mkdir $PROJ_NAME/me
|
12
|
+
mkdir $PROJ_NAME/apps
|
13
|
+
mkdir $PROJ_NAME/infra
|
14
|
+
mkdir $PROJ_NAME/host
|
15
|
+
mkdir $PROJ_NAME/secrets
|
16
|
+
mkdir $PROJ_NAME/bin
|
17
|
+
|
18
|
+
cd $PROJ_NAME
|
19
|
+
|
20
|
+
echo "KUBECONFIG=$PROJ_NAME/me/kube/config" > me/dev.env
|
21
|
+
echo "HELM_HOME=$PROJ_NAME/me/helm" >> me/dev.env
|
22
|
+
echo "MINFRA_HOST_PATH=$PROJ_PATH" >> me/dev.env
|
data/exe/minfra
ADDED
data/lib/deep_merge.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
module Hashie
|
2
|
+
module Extensions
|
3
|
+
module DeepMergeConcat
|
4
|
+
|
5
|
+
def transform_values
|
6
|
+
result = self.class.new
|
7
|
+
each do |key, value|
|
8
|
+
result[key] = yield(value)
|
9
|
+
end
|
10
|
+
result
|
11
|
+
end
|
12
|
+
|
13
|
+
def transform_values!
|
14
|
+
each do |key, value|
|
15
|
+
self[key] = yield(value)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def transform_keys
|
20
|
+
result = self.class.new
|
21
|
+
each_key do |key|
|
22
|
+
result[yield(key)] = self[key]
|
23
|
+
end
|
24
|
+
result
|
25
|
+
end
|
26
|
+
|
27
|
+
def transform_keys!
|
28
|
+
keys.each do |key|
|
29
|
+
self[yield(key)] = delete(key)
|
30
|
+
end
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def deep_sort_by_key_and_sort_array(exclusions = [], &block)
|
35
|
+
self.keys.sort(&block).reduce({}) do |seed, key|
|
36
|
+
seed[key] = self[key]
|
37
|
+
unless exclusions.include?(key.to_s)
|
38
|
+
if seed[key].is_a?(Hash)
|
39
|
+
seed[key] = seed[key].deep_sort_by_key_and_sort_array(exclusions, &block)
|
40
|
+
elsif seed[key].is_a?(Hashie::Array)
|
41
|
+
seed[key] = seed[key].sort(&block)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
seed
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
49
|
+
def deep_sort(&block)
|
50
|
+
copy = dup
|
51
|
+
copy.extend(Hashie::Extensions::DeepMergeConcat) unless copy.respond_to?(:deep_sort!)
|
52
|
+
copy.deep_sort!(&block)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
56
|
+
# Modifies the receiver in place.
|
57
|
+
def deep_sort!(&block)
|
58
|
+
_recursive_sort(self, &block)
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
63
|
+
def deep_merge_concat(other_hash, &block)
|
64
|
+
copy = dup
|
65
|
+
copy.extend(Hashie::Extensions::DeepMergeConcat) unless copy.respond_to?(:deep_merge_concat!)
|
66
|
+
copy.deep_merge_concat!(other_hash, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
70
|
+
# Modifies the receiver in place.
|
71
|
+
def deep_merge_concat!(other_hash, &block)
|
72
|
+
return self unless other_hash.is_a?(::Hash)
|
73
|
+
_recursive_merge_concat(self, other_hash, &block)
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
def deep_transform_values(&block)
|
78
|
+
_deep_transform_values_in_object(self, &block)
|
79
|
+
end
|
80
|
+
|
81
|
+
def deep_transform_values!(&block)
|
82
|
+
_deep_transform_values_in_object!(self, &block)
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def _deep_transform_values_in_object(object, &block)
|
88
|
+
case object
|
89
|
+
when Hash
|
90
|
+
object.each_with_object({}) do |arg, result|
|
91
|
+
key = arg.first
|
92
|
+
value = arg.last
|
93
|
+
result[key] = _deep_transform_values_in_object(value, &block)
|
94
|
+
end
|
95
|
+
when Array
|
96
|
+
object.map {|e| _deep_transform_values_in_object(e, &block) }
|
97
|
+
else
|
98
|
+
yield(object)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def _deep_transform_values_in_object!(object, &block)
|
103
|
+
case object
|
104
|
+
when Hash
|
105
|
+
object.each do |key, value|
|
106
|
+
object[key] = _deep_transform_values_in_object!(value, &block)
|
107
|
+
end
|
108
|
+
when Array
|
109
|
+
object.map! {|e| _deep_transform_values_in_object!(e, &block) }
|
110
|
+
else
|
111
|
+
yield(object)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def _recursive_sort(object, &block)
|
116
|
+
case object
|
117
|
+
when Hash
|
118
|
+
object = Orchparty::AST::Node.new(object.sort {|a, b| block.call(a[0], b[0]) }.to_h)
|
119
|
+
object.each do |key, value|
|
120
|
+
object[key] = _recursive_sort(value, &block)
|
121
|
+
end
|
122
|
+
object
|
123
|
+
when Array
|
124
|
+
object.map! {|e| _recursive_sort(e, &block) }.sort(&block)
|
125
|
+
else
|
126
|
+
yield(object)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
def _recursive_merge_concat(hash, other_hash, &block)
|
132
|
+
other_hash.each do |k, v|
|
133
|
+
hash[k] = if hash.key?(k) && hash[k].is_a?(::Hash) && v.is_a?(::Hash)
|
134
|
+
_recursive_merge(hash[k], v, &block)
|
135
|
+
elsif hash.key?(k) && hash[k].is_a?(::Array) && v.is_a?(::Array)
|
136
|
+
hash[k].concat(v).uniq
|
137
|
+
else
|
138
|
+
if hash.key?(k) && block_given?
|
139
|
+
block.call(k, hash[k], v)
|
140
|
+
else
|
141
|
+
v.respond_to?(:deep_dup) ? v.deep_dup : v
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
hash
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
data/lib/hash.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
class HashUtils
|
2
|
+
def self.transform_hash(original, options={}, &block)
|
3
|
+
original.inject({}){|result, (key,value)|
|
4
|
+
value = if (options[:deep] && Hash === value)
|
5
|
+
transform_hash(value, options, &block)
|
6
|
+
else
|
7
|
+
if Array === value
|
8
|
+
value.map{|v|
|
9
|
+
if Hash === v
|
10
|
+
transform_hash(v, options, &block)
|
11
|
+
else
|
12
|
+
v
|
13
|
+
end}
|
14
|
+
else
|
15
|
+
value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
block.call(result,key,value)
|
19
|
+
result
|
20
|
+
}
|
21
|
+
end
|
22
|
+
# Convert keys to strings, recursively
|
23
|
+
def self.deep_stringify_keys(hash)
|
24
|
+
transform_hash(hash, :deep => true) {|hash, key, value|
|
25
|
+
hash[key.to_s] = value
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Minfra
|
2
|
+
module Cli
|
3
|
+
module Ask
|
4
|
+
def self.boolean(question)
|
5
|
+
answered = false
|
6
|
+
until answered
|
7
|
+
STDOUT.write "#{question} (y/n)"
|
8
|
+
answer = STDIN.gets.chomp
|
9
|
+
if ['y', 'n'].include?(answer)
|
10
|
+
answered = true
|
11
|
+
else
|
12
|
+
STDOUT.write("I just understand 'y' and 'n', again: ")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
answer == 'y'
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.text(question, default=nil)
|
19
|
+
begin
|
20
|
+
message = format('%s%s: ', question, default && " (#{default})")
|
21
|
+
STDOUT.write message
|
22
|
+
answer = STDIN.gets.chomp
|
23
|
+
answer = default if answer == ''
|
24
|
+
end while answer.nil?
|
25
|
+
answer
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.placeholders(templater,placeholders={})
|
29
|
+
templater.check_missing do |name|
|
30
|
+
placeholders[name]=self.text("I need a value for: #{name}") unless placeholders[name]
|
31
|
+
end
|
32
|
+
placeholders
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.interactive_template(template_file, out_file, placeholders={})
|
36
|
+
templater=Templater.new(File.read(template_file))
|
37
|
+
params=self.placeholders(templater,placeholders)
|
38
|
+
File.write(out_file,templater.render(params))
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Minfra
|
2
|
+
module Cli
|
3
|
+
class Command < Thor
|
4
|
+
include Common
|
5
|
+
include Logging
|
6
|
+
include Hook
|
7
|
+
|
8
|
+
attr_reader :minfra_config
|
9
|
+
no_commands do
|
10
|
+
def invoke_command(*args)
|
11
|
+
begin
|
12
|
+
subcommand_name = args.first.name.to_sym
|
13
|
+
with_hook(subcommand_name) do
|
14
|
+
@minfra_config = Minfra::Cli.config
|
15
|
+
@minfra_config.load(options['environment']) if options['environment']
|
16
|
+
@cli_args = args[1]
|
17
|
+
super(*args)
|
18
|
+
end
|
19
|
+
rescue Minfra::Cli::Config::ConfigNotFoundError => err
|
20
|
+
STDERR.puts(err.message)
|
21
|
+
STDERR.puts "please run 'minfra setup dev'"
|
22
|
+
exit 1
|
23
|
+
rescue Minfra::Cli::Config::EnvironmentNotFoundError => err
|
24
|
+
STDERR.puts(err.message)
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
def cli_args
|
29
|
+
@args
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
module Minfra
|
3
|
+
module Cli
|
4
|
+
class Dev < Command
|
5
|
+
|
6
|
+
desc "describe", "get some info about your config (if it's setup)"
|
7
|
+
option :environment, required: false, aliases: ['-e']
|
8
|
+
def describe
|
9
|
+
pp @minfra_config.describe(options[:environment])
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "create", "create your development cluster"
|
13
|
+
def create
|
14
|
+
kube.create
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "upgrade", "upgrade kind (moves previous configs and recreates the cluster; use it if you made changes to config/kind.yaml.erb)"
|
18
|
+
def upgrade
|
19
|
+
info "Destroying existing dev cluster.."
|
20
|
+
destroy
|
21
|
+
Runner.run("mv #{@minfra_config.base_path.join('me','kind.yaml.erb')} #{@minfra_config.base_path.join('me','kind_old_' + Time.now.strftime("%Y_%m_%dT%H_%M_%SZ") + '.yaml.erb')}", print_stdout: true)
|
22
|
+
Runner.run("mv #{@minfra_config.base_path.join('me', 'kube', 'config')} #{@minfra_config.base_path.join('me', 'kube', 'config_old_' + Time.now.strftime("%Y_%m_%dT%H_%M_%SZ"))}", print_stdout: true)
|
23
|
+
Runner.run('yes | minfra setup dev', print_stdout: true) # On an existing cluster this should only ask for recreating the files that we moved previously
|
24
|
+
info "Creating a new dev cluster.."
|
25
|
+
create
|
26
|
+
info "I am done upgrading the dev cluster! 🎉"
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "restart", "restart your development cluster"
|
30
|
+
def restart
|
31
|
+
kube.restart
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "start", "start your development cluster"
|
35
|
+
def start
|
36
|
+
restart
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "destroy", "tear down your development cluster"
|
40
|
+
def destroy
|
41
|
+
kube.destroy_dev_cluster
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def kube
|
47
|
+
@kube ||= Kube.new(options,minfra_config)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Minfra::Cli.register("dev", "Manage your dev cluster.", Minfra::Cli::Dev)
|