minfra-cli 1.13.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -2
- data/.rubocop.yml +31 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile.lock +1 -1
- data/README.md +13 -1
- data/exe/minfra +1 -3
- data/lib/deep_merge.rb +35 -36
- data/lib/hash.rb +19 -18
- data/lib/minfra/cli/ask.rb +18 -16
- data/lib/minfra/cli/cli_starter.rb +173 -0
- data/lib/minfra/cli/command.rb +4 -1
- data/lib/minfra/cli/commands/dev.rb +26 -15
- data/lib/minfra/cli/commands/kube.rb +97 -88
- data/lib/minfra/cli/commands/plugin.rb +9 -8
- data/lib/minfra/cli/commands/project/branch.rb +7 -5
- data/lib/minfra/cli/commands/project/tag.rb +7 -6
- data/lib/minfra/cli/commands/project.rb +40 -40
- data/lib/minfra/cli/commands/setup.rb +18 -18
- data/lib/minfra/cli/commands/stack/app_template.rb +10 -13
- data/lib/minfra/cli/commands/stack/client_template.rb +10 -8
- data/lib/minfra/cli/commands/stack/kube_stack_template.rb +49 -51
- data/lib/minfra/cli/commands/stack.rb +55 -46
- data/lib/minfra/cli/commands/tag.rb +9 -8
- data/lib/minfra/cli/common.rb +7 -10
- data/lib/minfra/cli/config.rb +36 -63
- data/lib/minfra/cli/core_ext.rb +7 -0
- data/lib/minfra/cli/document.rb +5 -2
- data/lib/minfra/cli/env.rb +24 -0
- data/lib/minfra/cli/errors.rb +10 -0
- data/lib/minfra/cli/helm_runner.rb +3 -1
- data/lib/minfra/cli/hiera_looker.rb +54 -0
- data/lib/minfra/cli/hook.rb +36 -24
- data/lib/minfra/cli/kubectl_runner.rb +3 -1
- data/lib/minfra/cli/logging.rb +5 -1
- data/lib/minfra/cli/main_command.rb +2 -1
- data/lib/minfra/cli/plugin.rb +74 -0
- data/lib/minfra/cli/plugins.rb +18 -87
- data/lib/minfra/cli/runner.rb +23 -23
- data/lib/minfra/cli/templater.rb +17 -17
- data/lib/minfra/cli/version.rb +3 -1
- data/lib/minfra/cli.rb +20 -114
- data/lib/orchparty/ast.rb +13 -14
- data/lib/orchparty/cli.rb +35 -33
- data/lib/orchparty/context.rb +15 -15
- data/lib/orchparty/dsl_parser.rb +7 -11
- data/lib/orchparty/dsl_parser_kubernetes.rb +46 -56
- data/lib/orchparty/plugin.rb +10 -9
- data/lib/orchparty/plugins/env.rb +14 -13
- data/lib/orchparty/transformations/all.rb +3 -1
- data/lib/orchparty/transformations/mixin.rb +24 -24
- data/lib/orchparty/transformations/remove_internal.rb +3 -2
- data/lib/orchparty/transformations/sort.rb +2 -1
- data/lib/orchparty/transformations/variable.rb +6 -5
- data/lib/orchparty/transformations.rb +2 -0
- data/lib/orchparty/version.rb +3 -1
- data/lib/orchparty.rb +14 -14
- metadata +9 -2
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'yaml'
|
2
4
|
module Minfra
|
3
5
|
module Cli
|
@@ -9,27 +11,27 @@ module Minfra
|
|
9
11
|
|
10
12
|
def initialize(options, config)
|
11
13
|
@options = options
|
12
|
-
@config=config
|
13
|
-
@env_config=config.orch_env_config
|
14
|
+
@config = config
|
15
|
+
@env_config = config.orch_env_config
|
14
16
|
end
|
15
17
|
|
16
|
-
def dashboard(stack_name,env,deployment,cluster)
|
17
|
-
stack = init(stack_name,env,deployment,cluster)
|
18
|
-
insecure_flag = l(
|
18
|
+
def dashboard(stack_name, env, deployment, cluster)
|
19
|
+
stack = init(stack_name, env, deployment, cluster)
|
20
|
+
insecure_flag = l('infra::allow_insecure_k8s_connections') ? '--insecure-skip-tls-verify' : ''
|
19
21
|
cmd = "k9s #{insecure_flag} --kubeconfig #{kube_config_path} --context #{stack.cluster_name} --namespace #{stack_name} --command pod"
|
20
22
|
debug(cmd)
|
21
23
|
exec(cmd)
|
22
24
|
end
|
23
25
|
|
24
26
|
def restart
|
25
|
-
run %
|
26
|
-
run %
|
27
|
-
run %
|
28
|
-
run %
|
27
|
+
run %(docker start #{kind_name}-control-plane)
|
28
|
+
run %(docker exec #{kind_name}-control-plane bash -c "sed -e '/nameserver 127.0.0.11/ s/^#*/#/' /etc/resolv.conf | cat - >> /etc/resolv.conf")
|
29
|
+
run %(docker exec #{kind_name}-control-plane bash -c "echo nameserver 8.8.8.8 >> /etc/resolv.conf")
|
30
|
+
run %(docker exec #{kind_name}-control-plane bash -c "echo nameserver 8.8.4.4 >> /etc/resolv.conf")
|
29
31
|
end
|
30
32
|
|
31
33
|
def create
|
32
|
-
|
34
|
+
$stdout.sync
|
33
35
|
|
34
36
|
network_mask = @config.project.kind.network.mask
|
35
37
|
gateway_ip = @config.project.kind.network.gateway
|
@@ -37,82 +39,98 @@ module Minfra
|
|
37
39
|
|
38
40
|
info "step: creating network #{kind_name} #{network_mask} gw #{gateway_ip}"
|
39
41
|
# run(%{docker network inspect kind | grep "Subnet"}, exit_on_error: false).success?
|
40
|
-
run(%
|
42
|
+
run(%(docker network rm #{kind_name}), exit_on_error: false)
|
41
43
|
|
42
|
-
run(%
|
44
|
+
run(%(docker network create --gateway #{gateway_ip} --subnet=#{network_mask} #{kind_name}), exit_on_error: true)
|
43
45
|
|
44
46
|
info "step: creating '#{kind_name}' kind cluster (can take some minutes)"
|
45
|
-
kind_kube_path=Runner.run('echo $KUBECONFIG').to_s.strip
|
46
|
-
kind_config=Templater.read(config.base_path.join('config','kind.yaml.erb'), params: {config:
|
47
|
+
kind_kube_path = Runner.run('echo $KUBECONFIG').to_s.strip
|
48
|
+
kind_config = Templater.read(config.base_path.join('config', 'kind.yaml.erb'), params: { config: })
|
47
49
|
File.write(config.kind_config_path, kind_config)
|
48
|
-
|
49
|
-
run(%{KIND_EXPERIMENTAL_DOCKER_NETWORK=#{kind_name} kind create cluster --name "#{kind_name}" --config #{@config.kind_config_path}})
|
50
|
-
|
51
|
-
info "step: configuring kind"
|
52
|
-
run %{docker exec #{kind_name}-control-plane bash -c "sed -e '/nameserver 127.0.0.11/ s/^#*/#/' /etc/resolv.conf | cat - >> /etc/resolv.conf"}
|
53
|
-
run %{docker exec #{kind_name}-control-plane bash -c "echo nameserver 8.8.8.8 >> /etc/resolv.conf"}
|
54
|
-
run %{docker exec #{kind_name}-control-plane bash -c "echo nameserver 8.8.4.4 >> /etc/resolv.conf"}
|
55
|
-
|
56
|
-
configs = [YAML.load(File.read(kind_kube_path))]
|
57
|
-
|
58
|
-
existing_config = YAML.load(File.read(kube_config_path))
|
59
50
|
|
60
|
-
|
61
|
-
|
62
|
-
|
51
|
+
run(%(KIND_EXPERIMENTAL_DOCKER_NETWORK=#{kind_name} kind create cluster --name "#{kind_name}" --config #{@config.kind_config_path}))
|
52
|
+
|
53
|
+
info 'step: configuring kind'
|
54
|
+
run %(docker exec #{kind_name}-control-plane bash -c "sed -e '/nameserver 127.0.0.11/ s/^#*/#/' /etc/resolv.conf | cat - >> /etc/resolv.conf")
|
55
|
+
run %(docker exec #{kind_name}-control-plane bash -c "echo nameserver 8.8.8.8 >> /etc/resolv.conf")
|
56
|
+
run %(docker exec #{kind_name}-control-plane bash -c "echo nameserver 8.8.4.4 >> /etc/resolv.conf")
|
57
|
+
|
58
|
+
configs = [YAML.safe_load(File.read(kind_kube_path))]
|
59
|
+
|
60
|
+
existing_config = YAML.safe_load(File.read(kube_config_path))
|
61
|
+
|
62
|
+
existing_config['clusters'] = existing_config['clusters'].reject do |c|
|
63
|
+
configs.map do |k|
|
64
|
+
k['clusters']
|
65
|
+
end.flatten.map { |n| n['name'] }.include?(c['name'])
|
66
|
+
end.concat(configs.map do |k|
|
67
|
+
k['clusters']
|
68
|
+
end.flatten)
|
69
|
+
existing_config['users'] = existing_config['users'].reject do |c|
|
70
|
+
configs.map do |k|
|
71
|
+
k['users']
|
72
|
+
end.flatten.map { |n| n['name'] }.include?(c['name'])
|
73
|
+
end.concat(configs.map do |k|
|
74
|
+
k['users']
|
75
|
+
end.flatten).uniq { |k| k['name'] }
|
76
|
+
existing_config['contexts'] = existing_config['contexts'].reject do |c|
|
77
|
+
configs.map do |k|
|
78
|
+
k['contexts']
|
79
|
+
end.flatten.map { |n| n['name'] }.include?(c['name'])
|
80
|
+
end.concat(configs.map do |k|
|
81
|
+
k['contexts']
|
82
|
+
end.flatten)
|
63
83
|
File.write(@config.kube_config_path, YAML.dump(existing_config))
|
64
84
|
|
65
|
-
info
|
66
|
-
run_kubectl %
|
85
|
+
info 'step: starting kind'
|
86
|
+
run_kubectl %( config use-context kind-#{kind_name} )
|
67
87
|
|
68
|
-
run_kubectl %
|
88
|
+
run_kubectl %(create clusterrolebinding default-admin --serviceaccount=kube-system:default --clusterrole=cluster-admin)
|
69
89
|
|
70
|
-
# info "step: attaching newly created kind cluster to its own docker network"
|
71
|
-
# info run(%{docker network connect #{kind_name} #{kind_name}-control-plane --ip #{panel_ip}})
|
90
|
+
# info "step: attaching newly created kind cluster to its own docker network"
|
91
|
+
# info run(%{docker network connect #{kind_name} #{kind_name}-control-plane --ip #{panel_ip}})
|
72
92
|
end
|
73
93
|
|
74
94
|
def push(image)
|
75
|
-
run %
|
95
|
+
run %(kind load docker-image --name #{kind_name} #{image})
|
76
96
|
end
|
77
97
|
|
78
98
|
def destroy_dev_cluster
|
79
99
|
run %(kind delete cluster --name #{kind_name})
|
80
100
|
run(%(docker rm -f #{kind_name}-control-plane), exit_on_error: false)
|
81
|
-
run(%(docker network rm #{kind_name}), exit_on_error: false)
|
101
|
+
run(%(docker network rm #{kind_name}), exit_on_error: false)
|
82
102
|
end
|
83
103
|
|
84
104
|
def deploy(stack_name, reason_message)
|
85
|
-
#TBD: options is global, avoid it!
|
86
|
-
|
87
|
-
test=options[:test]
|
105
|
+
# TBD: options is global, avoid it!
|
106
|
+
|
107
|
+
test = options[:test]
|
88
108
|
stack = init(stack_name,
|
89
109
|
options[:environment],
|
90
110
|
options[:deployment],
|
91
111
|
options[:cluster])
|
92
112
|
cluster = stack.cluster_name
|
93
113
|
|
94
|
-
method = options[
|
114
|
+
method = options['install'] ? 'install' : 'upgrade'
|
95
115
|
|
96
116
|
stack.release_path.mkpath
|
97
|
-
|
98
|
-
File.open(stack.compose_path,
|
99
|
-
Orchparty::App.new(cluster_name: cluster,
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
)
|
106
|
-
print( method: method, out_io: f)
|
117
|
+
|
118
|
+
File.open(stack.compose_path, 'w') do |f|
|
119
|
+
Orchparty::App.new(cluster_name: cluster,
|
120
|
+
application_name: stack.name,
|
121
|
+
force_variable_definition: false,
|
122
|
+
file_name: stack.stack_rb_path.to_s,
|
123
|
+
status_dir: stack.release_path,
|
124
|
+
options:)
|
125
|
+
.print(method:, out_io: f)
|
107
126
|
end
|
108
|
-
#run_cmd(generate_cmd, :bash)
|
127
|
+
# run_cmd(generate_cmd, :bash)
|
109
128
|
bash_cmd = ["cd #{stack.release_path}"]
|
110
129
|
run_cmd(bash_cmd, :bash)
|
111
130
|
|
112
|
-
|
113
131
|
run_cmd(["cd #{stack.release_path}",
|
114
|
-
"git --no-pager diff #{stack.release_path}",
|
115
|
-
|
132
|
+
"git --no-pager diff #{stack.release_path}"], :bash, silence: true)
|
133
|
+
# run_cmd("helm diff upgrade --allow-unreleased ccs-integration-service state/stacks/development-staging-1/ccs-integration-service/helm -n ccs-integration-service", :bash, silence: true)
|
116
134
|
|
117
135
|
errors = stack.check_plan
|
118
136
|
unless errors.empty?
|
@@ -123,25 +141,20 @@ module Minfra
|
|
123
141
|
end
|
124
142
|
end
|
125
143
|
|
126
|
-
|
127
|
-
unless @config.dev? || options[:force]==true
|
128
|
-
unless Ask.boolean("Are the changes ok?")
|
129
|
-
exit_error("Deployment aborted!")
|
130
|
-
end
|
131
|
-
end
|
144
|
+
return if test
|
132
145
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
146
|
+
exit_error('Deployment aborted!') if !(@config.dev? || options[:force] == true) && !Ask.boolean('Are the changes ok?')
|
147
|
+
|
148
|
+
message = "deploying stack #{stack.name}: #{reason_message}."
|
149
|
+
Minfra::Cli::Document.document(@config, "started #{message}")
|
150
|
+
orch = Orchparty::App.new(cluster_name: cluster,
|
151
|
+
application_name: stack.name,
|
152
|
+
force_variable_definition: false,
|
153
|
+
file_name: stack.stack_rb_path.to_s,
|
154
|
+
status_dir: stack.release_path,
|
155
|
+
options:)
|
156
|
+
orch.send(method)
|
157
|
+
Minfra::Cli::Document.document(@config, "finished #{message}")
|
145
158
|
end
|
146
159
|
|
147
160
|
def rollback(stack_name, env, deployment, cluster)
|
@@ -153,7 +166,7 @@ module Minfra
|
|
153
166
|
cluster = stack.cluster_name
|
154
167
|
|
155
168
|
extra_args = args.dup
|
156
|
-
extra_args.delete(
|
169
|
+
extra_args.delete('rollback')
|
157
170
|
|
158
171
|
extra_args = extra_args.join(' ')
|
159
172
|
|
@@ -161,7 +174,7 @@ module Minfra
|
|
161
174
|
end
|
162
175
|
|
163
176
|
def list
|
164
|
-
puts run_helm(%
|
177
|
+
puts run_helm(%(list --all-namespaces))
|
165
178
|
end
|
166
179
|
|
167
180
|
def destroy(stack_name)
|
@@ -176,13 +189,11 @@ module Minfra
|
|
176
189
|
end
|
177
190
|
|
178
191
|
def kubectl_command(args)
|
179
|
-
unless options['stack']
|
180
|
-
exit_error("You must specify a stack name (--stack).")
|
181
|
-
end
|
192
|
+
exit_error('You must specify a stack name (--stack).') unless options['stack']
|
182
193
|
|
183
194
|
subcommand = args.shift
|
184
195
|
|
185
|
-
if [
|
196
|
+
if %w[exec logs port-forward].include?(subcommand)
|
186
197
|
resource = nil
|
187
198
|
implicit_resource = 'pod'
|
188
199
|
else
|
@@ -195,7 +206,8 @@ module Minfra
|
|
195
206
|
options[:cluster])
|
196
207
|
|
197
208
|
cluster = stack.cluster_name
|
198
|
-
if [resource,
|
209
|
+
if [resource,
|
210
|
+
implicit_resource].include?('pod') && %w[delete describe exec logs port-forward].include?(subcommand)
|
199
211
|
cmd_get_pods = "--kubeconfig #{kube_config_path} --context #{cluster} --namespace #{options[:stack]} get pod -o jsonpath='{range .items[*]}{.metadata.name}{\"\\n\"}'"
|
200
212
|
|
201
213
|
pods_list = run_kubectl(cmd_get_pods).stdout_lines
|
@@ -204,9 +216,7 @@ module Minfra
|
|
204
216
|
|
205
217
|
matching_pods = pods_list.select { |p| p.include?(fuzzy_pod_name) }
|
206
218
|
|
207
|
-
if matching_pods.empty?
|
208
|
-
exit_error("Could not find any pods that have '#{fuzzy_pod_name}' in their name.")
|
209
|
-
end
|
219
|
+
exit_error("Could not find any pods that have '#{fuzzy_pod_name}' in their name.") if matching_pods.empty?
|
210
220
|
|
211
221
|
position = 0
|
212
222
|
if options[:position]
|
@@ -237,14 +247,13 @@ module Minfra
|
|
237
247
|
|
238
248
|
private
|
239
249
|
|
240
|
-
def init(stack_name,
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
250
|
+
def init(stack_name, _env, deployment, explicit_cluster)
|
251
|
+
Minfra::Cli::StackM::KubeStackTemplate.new(stack_name,
|
252
|
+
config,
|
253
|
+
deployment:,
|
254
|
+
cluster: explicit_cluster)
|
245
255
|
|
246
|
-
# exit_error(template.error_message) unless template.valid?
|
247
|
-
template
|
256
|
+
# exit_error(template.error_message) unless template.valid?
|
248
257
|
end
|
249
258
|
|
250
259
|
def kube_config_path
|
@@ -1,21 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Minfra
|
2
4
|
module Cli
|
3
5
|
class Plugin < Command
|
4
|
-
|
5
|
-
desc "describe","describe plugins"
|
6
|
+
desc 'describe', 'describe plugins'
|
6
7
|
def describe
|
7
|
-
Minfra::Cli.plugins.each do |plugin|
|
8
|
+
Minfra::Cli.cli.plugins.each do |plugin|
|
8
9
|
puts "#{plugin.name} (#{plugin.version})"
|
9
10
|
end
|
10
11
|
end
|
11
|
-
desc
|
12
|
+
desc 'install', 'install plugins'
|
12
13
|
def install
|
13
|
-
Minfra::Cli.plugins.each do |plugin|
|
14
|
+
Minfra::Cli.cli.plugins.each do |plugin|
|
14
15
|
puts "setup: #{plugin.name}"
|
15
16
|
plugin.install
|
16
17
|
end
|
17
18
|
end
|
18
|
-
end
|
19
|
-
end
|
19
|
+
end
|
20
|
+
end
|
20
21
|
end
|
21
|
-
Minfra::Cli.register(
|
22
|
+
Minfra::Cli.register('plugin', 'dealing wit plugins', Minfra::Cli::Plugin)
|
@@ -1,18 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Minfra
|
2
4
|
module Cli
|
3
5
|
class Project < Command
|
4
6
|
class Branch < Command
|
5
|
-
|
6
7
|
desc "create 'story desc'", 'create branch'
|
7
|
-
option :prefix, type: :string,
|
8
|
+
option :prefix, type: :string,
|
9
|
+
desc: "don't use your git email address or project.branch.create.prefix or identity.email"
|
8
10
|
def create(story_desc)
|
9
|
-
story_desc = story_desc.gsub(/[^0-9a-z
|
10
|
-
prefix = options[:prefix] || Minfra::Cli.config.project.dig('project','branch', 'create', 'prefix')
|
11
|
+
story_desc = story_desc.gsub(/[^0-9a-z-]/i, '_')
|
12
|
+
prefix = options[:prefix] || Minfra::Cli.config.project.dig('project', 'branch', 'create', 'prefix')
|
11
13
|
unless prefix
|
12
14
|
email = Minfra::Cli.config.project.dig('identity', 'email') || `git config user.email`
|
13
15
|
fullname = email.split('@').first
|
14
16
|
prefix = fullname[0] + fullname.split('.').last
|
15
|
-
end
|
17
|
+
end
|
16
18
|
Runner.run("git checkout -b #{prefix}_#{story_desc}_$(date +%Y%m%d)")
|
17
19
|
end
|
18
20
|
end
|
@@ -1,18 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Minfra
|
2
4
|
module Cli
|
3
5
|
class Project < Command
|
4
6
|
class Tag < Command
|
5
|
-
|
6
|
-
|
7
|
-
option "environment", aliases: ['-e'], required: true
|
7
|
+
desc 'update', 'update stack tag file'
|
8
|
+
option 'environment', aliases: ['-e'], required: true
|
8
9
|
def update(domain, new_tag)
|
9
10
|
tags = JSON.parse(File.read(tags_path))
|
10
11
|
|
11
|
-
raise ArgumentError
|
12
|
+
raise ArgumentError, "#{path} doesn't contain #{domain}" unless tags[options[:environment]].key?(domain)
|
12
13
|
|
13
14
|
tags[options[:environment]][domain] = new_tag
|
14
15
|
pretty_tags = JSON.pretty_unparse(tags)
|
15
|
-
File.write(tags_path, pretty_tags
|
16
|
+
File.write(tags_path, "#{pretty_tags}\n")
|
16
17
|
puts "#{tags_path} - UPDATED"
|
17
18
|
puts pretty_tags
|
18
19
|
end
|
@@ -35,6 +36,6 @@ module Minfra
|
|
35
36
|
Dir.getwd
|
36
37
|
end
|
37
38
|
end
|
38
|
-
end
|
39
|
+
end
|
39
40
|
end
|
40
41
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'project/branch'
|
2
4
|
require_relative 'project/tag'
|
3
5
|
|
@@ -11,19 +13,23 @@ module Minfra
|
|
11
13
|
attr_reader :app_dir
|
12
14
|
|
13
15
|
def initialize(app_dir)
|
14
|
-
@app_dir=app_dir
|
15
|
-
@project_file_path=app_dir.join('project.json')
|
16
|
-
@info=Hashie::Mash.new(JSON.parse(File.read(@project_file_path)))
|
16
|
+
@app_dir = app_dir
|
17
|
+
@project_file_path = app_dir.join('project.json')
|
18
|
+
@info = Hashie::Mash.new(JSON.parse(File.read(@project_file_path)))
|
17
19
|
end
|
20
|
+
|
18
21
|
def repo_name
|
19
22
|
"#{docker.repo}/#{docker.name}"
|
20
23
|
end
|
24
|
+
|
21
25
|
def name
|
22
26
|
@info['project']
|
23
27
|
end
|
28
|
+
|
24
29
|
def method_missing(method)
|
25
30
|
@info.send(method)
|
26
31
|
end
|
32
|
+
|
27
33
|
def inspect
|
28
34
|
@info.inspect
|
29
35
|
end
|
@@ -35,7 +41,7 @@ module Minfra
|
|
35
41
|
desc 'tag', 'manage tags'
|
36
42
|
subcommand 'tag', Tag
|
37
43
|
|
38
|
-
desc
|
44
|
+
desc 'test', 'run tests'
|
39
45
|
def test
|
40
46
|
ARGV.delete('project') # ARGV is passed along to `rspec` call
|
41
47
|
ARGV.delete('test')
|
@@ -51,63 +57,57 @@ module Minfra
|
|
51
57
|
end
|
52
58
|
end
|
53
59
|
|
54
|
-
desc
|
55
|
-
option
|
56
|
-
option
|
60
|
+
desc 'build', 'build a local build'
|
61
|
+
option 'noload', aliases: ['-n']
|
62
|
+
option 'target', aliases: ['-t']
|
57
63
|
def build
|
58
|
-
p=ProjectInfo.load(Pathname.pwd)
|
64
|
+
p = ProjectInfo.load(Pathname.pwd)
|
59
65
|
run_pre_repo
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
target = p.docker.dev_target
|
64
|
-
end
|
65
|
-
|
66
|
-
cmd = %{docker build #{"--target #{target}" if target} -t #{p.repo_name}:latest #{p.app_dir}}
|
66
|
+
target = options[:target] || p.docker.dev_target
|
67
|
+
|
68
|
+
cmd = %(docker build #{"--target #{target}" if target} -t #{p.repo_name}:latest #{p.app_dir})
|
67
69
|
res = Runner.run(cmd)
|
68
70
|
exit(1) if res.error?
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
|
72
|
+
return if options[:noload]
|
73
|
+
|
74
|
+
debug("loading image into KIND's registry")
|
75
|
+
Runner.run(%(kind load docker-image #{p.repo_name}:latest --name #{minfra_config.name}))
|
74
76
|
end
|
75
77
|
|
76
|
-
desc
|
77
|
-
def exec(cmd='/bin/bash')
|
78
|
-
p=ProjectInfo.load(Pathname.pwd)
|
78
|
+
desc 'exec', 'execute a command (bash is default in the container)'
|
79
|
+
def exec(cmd = '/bin/bash')
|
80
|
+
p = ProjectInfo.load(Pathname.pwd)
|
79
81
|
run_pre_repo
|
80
|
-
Kernel.exec(%
|
82
|
+
Kernel.exec(%(docker run -ti --rm #{p.exec_params} -v #{p.app_dir}:/code #{p.repo_name}:latest #{cmd}))
|
81
83
|
end
|
82
84
|
|
83
|
-
desc
|
85
|
+
desc 'push', 'push directly to the repo'
|
84
86
|
option 'tag', aliases: ['-t']
|
85
87
|
option 'registry', aliases: ['-r']
|
86
88
|
def push
|
87
89
|
tag = options[:tag] || `date +%Y%m%d%H%M`
|
88
|
-
p=ProjectInfo.load(Pathname.pwd)
|
90
|
+
p = ProjectInfo.load(Pathname.pwd)
|
89
91
|
|
90
92
|
repo_name = if options[:registry]
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
Runner.run(%{docker build -t #{p.repo_name}:latest #{p.app_dir}})
|
97
|
-
# Runner.run(%{docker push #{p.repo_name}})
|
98
|
-
Runner.run(%{docker tag #{p.repo_name}:latest #{repo_name}:#{tag}})
|
99
|
-
Runner.run(%{docker push #{repo_name}:#{tag}})
|
100
|
-
end
|
101
|
-
|
93
|
+
"#{options[:registry]}/#{p.repo_name}"
|
94
|
+
else
|
95
|
+
p.repo_name
|
96
|
+
end
|
102
97
|
|
98
|
+
Runner.run(%(docker build -t #{p.repo_name}:latest #{p.app_dir}))
|
99
|
+
# Runner.run(%{docker push #{p.repo_name}})
|
100
|
+
Runner.run(%(docker tag #{p.repo_name}:latest #{repo_name}:#{tag}))
|
101
|
+
Runner.run(%(docker push #{repo_name}:#{tag}))
|
102
|
+
end
|
103
103
|
|
104
104
|
private
|
105
|
+
|
105
106
|
def run_pre_repo
|
106
|
-
Runner.run(
|
107
|
+
Runner.run(minfra_config.base_path.join('hooks', 'pre_repo.sh').to_s)
|
107
108
|
end
|
108
109
|
end
|
109
110
|
end
|
110
111
|
end
|
111
112
|
|
112
|
-
|
113
|
-
Minfra::Cli.register("project", "dealing wit projects", Minfra::Cli::Project)
|
113
|
+
Minfra::Cli.register('project', 'dealing wit projects', Minfra::Cli::Project)
|
@@ -1,11 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fileutils'
|
2
4
|
module Minfra
|
3
5
|
module Cli
|
4
|
-
|
6
|
+
# not from command! # Dev
|
7
|
+
class Setup < Thor
|
5
8
|
include Logging
|
6
9
|
include Hook
|
7
10
|
|
8
|
-
desc
|
11
|
+
desc 'dev', 'creates a default config file on the host'
|
9
12
|
def dev
|
10
13
|
setup_config
|
11
14
|
end
|
@@ -13,31 +16,28 @@ module Minfra
|
|
13
16
|
private
|
14
17
|
|
15
18
|
def setup_config
|
16
|
-
config= Minfra::Cli.config
|
17
|
-
ensure_path_and_template(config.config_path, config.base_path.join('config','me_config.json.erb'))
|
19
|
+
config = Minfra::Cli.config
|
20
|
+
ensure_path_and_template(config.config_path, config.base_path.join('config', 'me_config.json.erb'))
|
18
21
|
config.init!
|
19
22
|
config.load('dev')
|
20
|
-
|
21
23
|
end
|
22
24
|
|
23
|
-
def ensure_path_and_template(dest_path, template_path, params={})
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
template=Ask.interactive_template(template_path,dest_path,params)
|
31
|
-
else
|
32
|
-
error "Leaving your filesystem untouched! But I have to stop!"
|
33
|
-
exit 1
|
25
|
+
def ensure_path_and_template(dest_path, template_path, params = {})
|
26
|
+
if dest_path.exist?
|
27
|
+
info "SETUP CONFIG: checked #{dest_path}"
|
28
|
+
elsif Ask.boolean("missing configuration at: #{dest_path}, should I create it?")
|
29
|
+
unless dest_path.dirname.exist?
|
30
|
+
info "Generated directory '#{dest_path.dirname}'"
|
31
|
+
FileUtils.mkdir_p(dest_path.dirname)
|
34
32
|
end
|
33
|
+
template = Ask.interactive_template(template_path, dest_path, params)
|
35
34
|
else
|
36
|
-
|
35
|
+
error 'Leaving your filesystem untouched! But I have to stop!'
|
36
|
+
exit 1
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
Minfra::Cli.register(
|
43
|
+
Minfra::Cli.register('setup', 'Manage your dev setup.', Minfra::Cli::Setup)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'pathname'
|
2
4
|
|
3
5
|
module Minfra
|
@@ -7,6 +9,7 @@ module Minfra
|
|
7
9
|
include ::Minfra::Cli::Logging
|
8
10
|
|
9
11
|
attr_reader :name, :env, :deployment, :app_path
|
12
|
+
|
10
13
|
def initialize(name, config)
|
11
14
|
@name = name
|
12
15
|
@path = config.stacks_path.join(name)
|
@@ -19,11 +22,10 @@ module Minfra
|
|
19
22
|
|
20
23
|
def cluster_name
|
21
24
|
return @cluster_name if defined?(@cluster_name)
|
25
|
+
|
22
26
|
@cluster_name = @cluster
|
23
27
|
@cluster_name ||= "kind-#{@config.name}" if @config.dev?
|
24
|
-
if cluster_path.exist? && (@cluster_name.nil? || @cluster_name.empty?)
|
25
|
-
@cluster_name = YAML.load(File.read(cluster_path))[env.to_s]
|
26
|
-
end
|
28
|
+
@cluster_name = YAML.safe_load(File.read(cluster_path))[env.to_s] if cluster_path.exist? && (@cluster_name.nil? || @cluster_name.empty?)
|
27
29
|
unless @cluster_name
|
28
30
|
error "Cluster name unknown (not given explicitly and '#{cluster_path}' missing)"
|
29
31
|
exit 1
|
@@ -32,18 +34,14 @@ module Minfra
|
|
32
34
|
end
|
33
35
|
|
34
36
|
def valid?
|
35
|
-
unless @path.exist?
|
36
|
-
@errors << "stack path #{@path} doesn't exist"
|
37
|
-
end
|
37
|
+
@errors << "stack path #{@path} doesn't exist" unless @path.exist?
|
38
38
|
|
39
|
-
unless @app_path.exist?
|
40
|
-
@errors << "stack.rb file #{@app_path} doesn't exist"
|
41
|
-
end
|
39
|
+
@errors << "stack.rb file #{@app_path} doesn't exist" unless @app_path.exist?
|
42
40
|
@errors.empty?
|
43
41
|
end
|
44
42
|
|
45
43
|
def read
|
46
|
-
t=Minfra::Cli::Templater.new(File.read(@app_path))
|
44
|
+
t = Minfra::Cli::Templater.new(File.read(@app_path))
|
47
45
|
@content = Hashie::Mash.new(JSON.parse(t.render({})))
|
48
46
|
end
|
49
47
|
|
@@ -54,11 +52,10 @@ module Minfra
|
|
54
52
|
def client
|
55
53
|
@content.client
|
56
54
|
end
|
57
|
-
|
55
|
+
|
58
56
|
def to_s
|
59
|
-
JSON.generate(@content, {indent:
|
57
|
+
JSON.generate(@content, { indent: ' ', object_nl: "\n" })
|
60
58
|
end
|
61
|
-
|
62
59
|
end
|
63
60
|
end
|
64
61
|
end
|