minfra-cli 1.13.3 → 2.0.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/.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
|