minfra-cli 1.13.2 → 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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -2
  3. data/.rubocop.yml +31 -0
  4. data/CHANGELOG.md +18 -1
  5. data/Gemfile.lock +1 -1
  6. data/README.md +13 -1
  7. data/exe/minfra +1 -3
  8. data/lib/deep_merge.rb +35 -36
  9. data/lib/hash.rb +19 -18
  10. data/lib/minfra/cli/ask.rb +18 -16
  11. data/lib/minfra/cli/cli_starter.rb +173 -0
  12. data/lib/minfra/cli/command.rb +4 -1
  13. data/lib/minfra/cli/commands/dev.rb +26 -15
  14. data/lib/minfra/cli/commands/kube.rb +97 -88
  15. data/lib/minfra/cli/commands/plugin.rb +9 -8
  16. data/lib/minfra/cli/commands/project/branch.rb +7 -5
  17. data/lib/minfra/cli/commands/project/tag.rb +7 -6
  18. data/lib/minfra/cli/commands/project.rb +40 -40
  19. data/lib/minfra/cli/commands/setup.rb +18 -18
  20. data/lib/minfra/cli/commands/stack/app_template.rb +10 -13
  21. data/lib/minfra/cli/commands/stack/client_template.rb +10 -8
  22. data/lib/minfra/cli/commands/stack/kube_stack_template.rb +49 -51
  23. data/lib/minfra/cli/commands/stack.rb +55 -46
  24. data/lib/minfra/cli/commands/tag.rb +9 -8
  25. data/lib/minfra/cli/common.rb +7 -10
  26. data/lib/minfra/cli/config.rb +36 -63
  27. data/lib/minfra/cli/core_ext.rb +7 -0
  28. data/lib/minfra/cli/document.rb +5 -2
  29. data/lib/minfra/cli/env.rb +24 -0
  30. data/lib/minfra/cli/errors.rb +10 -0
  31. data/lib/minfra/cli/helm_runner.rb +3 -1
  32. data/lib/minfra/cli/hiera_looker.rb +54 -0
  33. data/lib/minfra/cli/hook.rb +36 -24
  34. data/lib/minfra/cli/kubectl_runner.rb +3 -1
  35. data/lib/minfra/cli/logging.rb +5 -1
  36. data/lib/minfra/cli/main_command.rb +2 -1
  37. data/lib/minfra/cli/plugin.rb +74 -0
  38. data/lib/minfra/cli/plugins.rb +18 -87
  39. data/lib/minfra/cli/runner.rb +23 -23
  40. data/lib/minfra/cli/templater.rb +17 -17
  41. data/lib/minfra/cli/version.rb +3 -1
  42. data/lib/minfra/cli.rb +20 -114
  43. data/lib/orchparty/ast.rb +13 -14
  44. data/lib/orchparty/cli.rb +35 -33
  45. data/lib/orchparty/context.rb +15 -15
  46. data/lib/orchparty/dsl_parser.rb +7 -11
  47. data/lib/orchparty/dsl_parser_kubernetes.rb +46 -56
  48. data/lib/orchparty/kubernetes_application.rb +2 -2
  49. data/lib/orchparty/plugin.rb +10 -9
  50. data/lib/orchparty/plugins/env.rb +14 -13
  51. data/lib/orchparty/transformations/all.rb +3 -1
  52. data/lib/orchparty/transformations/mixin.rb +24 -24
  53. data/lib/orchparty/transformations/remove_internal.rb +3 -2
  54. data/lib/orchparty/transformations/sort.rb +2 -1
  55. data/lib/orchparty/transformations/variable.rb +6 -5
  56. data/lib/orchparty/transformations.rb +2 -0
  57. data/lib/orchparty/version.rb +3 -1
  58. data/lib/orchparty.rb +14 -14
  59. metadata +9 -2
data/lib/minfra/cli.rb CHANGED
@@ -1,9 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thor'
2
4
  require 'open3'
3
5
  require 'json'
4
6
  require 'ostruct'
5
7
  require 'hiera'
6
8
 
9
+ require_relative 'cli/core_ext'
10
+ require_relative 'cli/errors'
7
11
  require_relative 'cli/logging'
8
12
  require_relative 'cli/templater'
9
13
 
@@ -19,137 +23,39 @@ require_relative 'cli/runner'
19
23
  require_relative 'cli/helm_runner'
20
24
  require_relative 'cli/kubectl_runner'
21
25
  require_relative 'cli/plugins'
26
+ require_relative 'cli/plugin'
27
+ require_relative 'cli/hiera_looker'
28
+ require_relative 'cli/env'
29
+ require_relative 'cli/cli_starter'
22
30
 
23
31
  require 'active_support'
24
32
  require 'active_support/core_ext'
25
33
 
26
- require "#{ENV['MINFRA_PATH']}/config/preload.rb" if File.exist?("#{ENV['MINFRA_PATH']}/config/preload.rb")
34
+ require "#{ENV.fetch('MINFRA_PATH', nil)}/config/preload.rb" if File.exist?("#{ENV.fetch('MINFRA_PATH', nil)}/config/preload.rb")
27
35
 
28
36
  module Minfra
29
37
  module Cli
30
-
31
38
  extend Minfra::Cli::Logging
32
39
  include Minfra::Cli::Hook
33
40
 
34
- def self.logger
35
- @logger
36
- end
37
-
38
- def self.init(argv)
39
- @argv = argv
40
- # we'll set the context very early!
41
-
42
- if idx=@argv.index("-e")
43
- @config = Config.load(@argv[idx+1])
44
- @argv.delete_at(idx)
45
- @argv.delete_at(idx)
46
- else
47
- @config = Config.load('dev')
48
- end
49
-
50
- @logger=Logger.new(STDERR)
51
- logger.level=ENV["MINFRA_LOGGING_LEVEL"] || @config.project.minfra.logging_level || 'warn'
52
-
53
- project_minfrarc_path = @config.base_path.join("config",'minfrarc.rb')
54
- require project_minfrarc_path if project_minfrarc_path.exist?
55
- me_minfrarc_path = @config.me_path.join('minfrarc.rb')
56
- require @me_minfrarc_path if me_minfrarc_path.exist?
57
-
58
- @logger.debug("Minfra: loglevel: #{@logger.level}, env: #{@config.orch_env}")
59
-
60
- hiera_init
61
-
62
- @plugins = Minfra::Cli::Plugins.load
63
- @plugins.prepare
64
-
65
- Minfra::Cli.scan
66
- require_relative 'cli/main_command'
67
- Minfra::Cli.resolve
68
-
69
-
70
-
71
- end
72
-
73
- def self.run
74
- Minfra::Cli::Main.start(@argv)
75
- end
76
-
77
- def self.root_path
78
- Pathname.new(File.expand_path(File.join(__FILE__, '../../../')))
79
- end
80
-
81
- def self.hiera_init
82
- @hiera_root = Pathname.new("#{ENV["MINFRA_PATH"]}/hiera")
83
- hiera = Hiera.new(:config => @hiera_root.join('hiera.yaml').to_s)
84
- Hiera.logger=:noop
85
- env= @config.orch_env
86
- hiera_main_path=@hiera_root.join("hieradata/#{config.project.minfra.hiera.env_path}/#{env}.eyaml")
87
- raise("unknown environment #{env}, I expact a file at #{hiera_main_path}") unless hiera_main_path.exist?
88
-
89
- scope={ "minfra_path" => ENV["MINFRA_PATH"], "hieraroot" => @hiera_root.to_s, "env" => env}
90
- special_lookups=hiera.lookup("lookup_options", {}, scope, nil, :priority)
91
-
92
- node_scope=hiera.lookup("env", {}, scope, nil, :deeper)
93
- scope=scope.merge(node_scope)
94
- cache={}
95
- Kernel.define_method(:l) do |value,default=nil|
96
-
97
- return cache[value] if cache.has_key?(value)
98
-
99
- values=value.split(".")
100
- fst_value=values.shift
41
+ cattr_accessor :logger, :config, :subcommands,:cli
101
42
 
102
- if special_lookups[fst_value]
103
- lookup_type={ merge_behavior: special_lookups[fst_value]["merge"].to_sym }
104
- else
105
- lookup_type=:deep
106
- end
107
-
108
- result=hiera.lookup(fst_value, default, scope, nil, lookup_type)
109
- if !values.empty? && result.kind_of?(Hash) # we return nil or the scalar value and only drill down on hashes
110
- result=result.dig(*values)
111
- end
112
-
113
- result=Hashie::Mash.new(result) if result.kind_of?(Hash)
114
- cache[value] = result
115
- result
116
- end
117
- Kernel.define_method(:l!) do |value,default=nil|
118
- v=l(value,default)
119
- raise("Value not found! #{value}") if v.nil?
120
- v
121
- end
43
+ def self.init?
44
+ !!cli
122
45
  end
123
46
 
124
-
125
- def self.config
126
- @config
127
- end
128
-
129
- def self.scan
130
- #loading built in commands
131
- root_path.join("lib/minfra/cli/commands").each_child do |command_path|
132
- require command_path if command_path.to_s.match(/\.rb$/) && !command_path.to_s.match(/\#/)
133
- end
134
- @plugins.setup
135
- end
136
-
137
- def self.plugins
138
- @plugins
47
+ def self.init(argv = [])
48
+ self.subcommands ||= {}
49
+ self.cli = CliStarter.new(argv)
139
50
  end
140
51
 
141
- def self.register(subcommand,info,command)
142
- #debug("Registered command #{subcommand}")
143
- @subcommands ||= {}
144
- @subcommands[subcommand.to_sym]= OpenStruct.new(name: subcommand, info: info, command: command)
52
+ def self.exec(argv)
53
+ init(argv) unless init?
54
+ cli.run
145
55
  end
146
56
 
147
- def self.resolve
148
- @subcommands.values.each do |sub|
149
- Minfra::Cli::Main.desc(sub.name,sub.info)
150
- Minfra::Cli::Main.subcommand(sub.name,sub.command)
151
- end
57
+ def self.register(subcommand, info, command)
58
+ self.subcommands[subcommand.to_sym] = OpenStruct.new(name: subcommand, info:, command:)
152
59
  end
153
-
154
60
  end
155
61
  end
data/lib/orchparty/ast.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'hashie'
2
4
 
3
5
  module Orchparty
@@ -13,14 +15,12 @@ module Orchparty
13
15
  binding
14
16
  end
15
17
 
16
- def inspect(indent=0)
17
- start="\n"
18
+ def inspect(indent = 0)
19
+ start = "\n"
18
20
  each_pair do |name, ast|
19
- begin
20
- start << "#{' ' * indent}#{name}: #{ast.inspect(indent+1)}\n"
21
- rescue ArgumentError
22
- start << "#{' ' * indent}#{name}: #{ast.inspect}\n"
23
- end
21
+ start << "#{' ' * indent}#{name}: #{ast.inspect(indent + 1)}\n"
22
+ rescue ArgumentError
23
+ start << "#{' ' * indent}#{name}: #{ast.inspect}\n"
24
24
  end
25
25
  start
26
26
  end
@@ -39,28 +39,27 @@ module Orchparty
39
39
  end
40
40
 
41
41
  def self.mixin(args = {})
42
- Node.new({services: {}, _mixins: {}, volumes: {}, _variables: {}, networks: {}, _service_order: []}).merge(args)
42
+ Node.new({ services: {}, _mixins: {}, volumes: {}, _variables: {}, networks: {}, _service_order: [] }).merge(args)
43
43
  end
44
44
 
45
45
  def self.application(args = {})
46
- Node.new({services: {}, _mixins: {}, _mix:[], volumes: {}, _variables: {}, networks: {}, _service_order: []}).merge(args)
46
+ Node.new({ services: {}, _mixins: {}, _mix: [], volumes: {}, _variables: {}, networks: {}, _service_order: [] }).merge(args)
47
47
  end
48
48
 
49
49
  def self.all(args = {})
50
- Node.new(_mix:[], _variables: {}).merge(args)
50
+ Node.new(_mix: [], _variables: {}).merge(args)
51
51
  end
52
52
 
53
53
  def self.application_mixin(args = {})
54
- Node.new(_mix:[], _variables: {}).merge(args)
54
+ Node.new(_mix: [], _variables: {}).merge(args)
55
55
  end
56
56
 
57
57
  def self.service(args = {})
58
- Node.new(_mix:[], _variables: {}).merge(args)
58
+ Node.new(_mix: [], _variables: {}).merge(args)
59
59
  end
60
60
 
61
61
  def self.chart(args = {})
62
- Node.new(_mix:[], _variables: {}, _services: []).merge(args)
62
+ Node.new(_mix: [], _variables: {}, _services: []).merge(args)
63
63
  end
64
-
65
64
  end
66
65
  end
data/lib/orchparty/cli.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'orchparty'
2
4
  require 'gli'
3
5
 
@@ -11,57 +13,57 @@ class OrchPartyApp
11
13
 
12
14
  subcommand_option_handling :normal
13
15
 
14
- desc "install kubernetes application"
16
+ desc 'install kubernetes application'
15
17
  command :print do |com|
16
- com.flag [:cluster_name,:c,'cluster-name'], required: true, :desc => 'The cluster to install the app'
17
- com.flag [:filename,:f,'file-name'], required: true, :desc => 'The Orchparty input file'
18
- com.flag [:application,:a], required: true, :desc => 'The application that should be installed'
19
- com.switch :"force-variable-definition", :default_value => false, :desc => "Raises an Error if the input contains a not defined variable"
20
- com.flag [:method,:m], required: true, :desc => 'method to print upgrade/install'
18
+ com.flag [:cluster_name, :c, 'cluster-name'], required: true, desc: 'The cluster to install the app'
19
+ com.flag [:filename, :f, 'file-name'], required: true, desc: 'The Orchparty input file'
20
+ com.flag %i[application a], required: true, desc: 'The application that should be installed'
21
+ com.switch :'force-variable-definition', default_value: false, desc: 'Raises an Error if the input contains a not defined variable'
22
+ com.flag %i[method m], required: true, desc: 'method to print upgrade/install'
21
23
  com.action do |_, args|
22
- Orchparty.print(cluster_name: args[:c], application_name: args[:a], force_variable_definition: args["force-variable-definition"], file_name: args[:f], method: args[:m])
24
+ Orchparty.print(cluster_name: args[:c], application_name: args[:a], force_variable_definition: args['force-variable-definition'], file_name: args[:f], method: args[:m])
23
25
  end
24
26
  end
25
27
 
26
- desc "install kubernetes application"
28
+ desc 'install kubernetes application'
27
29
  command :install do |com|
28
- com.flag [:cluster_name,:c,'cluster-name'], required: true, :desc => 'The cluster to install the app'
29
- com.flag [:filename,:f,'file-name'], required: true, :desc => 'The Orchparty input file'
30
- com.flag [:application,:a], required: true, :desc => 'The application that should be installed'
31
- com.switch :"force-variable-definition", :default_value => false, :desc => "Raises an Error if the input contains a not defined variable"
30
+ com.flag [:cluster_name, :c, 'cluster-name'], required: true, desc: 'The cluster to install the app'
31
+ com.flag [:filename, :f, 'file-name'], required: true, desc: 'The Orchparty input file'
32
+ com.flag %i[application a], required: true, desc: 'The application that should be installed'
33
+ com.switch :'force-variable-definition', default_value: false, desc: 'Raises an Error if the input contains a not defined variable'
32
34
  com.action do |_, args|
33
- Orchparty.install(cluster_name: args[:c], application_name: args[:a], force_variable_definition: args["force-variable-definition"], file_name: args[:f])
35
+ Orchparty.install(cluster_name: args[:c], application_name: args[:a], force_variable_definition: args['force-variable-definition'], file_name: args[:f])
34
36
  end
35
37
  end
36
38
 
37
- desc "upgrade kubernetes application"
39
+ desc 'upgrade kubernetes application'
38
40
  command :upgrade do |com|
39
- com.flag [:cluster_name,:c,'cluster-name'], required: true, :desc => 'The cluster to install the app'
40
- com.flag [:filename,:f,'file-name'], required: true, :desc => 'The Orchparty input file'
41
- com.flag [:application,:a], required: true, :desc => 'The application that should be installed'
42
- com.switch :"force-variable-definition", :default_value => false, :desc => "Raises an Error if the input contains a not defined variable"
41
+ com.flag [:cluster_name, :c, 'cluster-name'], required: true, desc: 'The cluster to install the app'
42
+ com.flag [:filename, :f, 'file-name'], required: true, desc: 'The Orchparty input file'
43
+ com.flag %i[application a], required: true, desc: 'The application that should be installed'
44
+ com.switch :'force-variable-definition', default_value: false, desc: 'Raises an Error if the input contains a not defined variable'
43
45
  com.action do |_, args|
44
- Orchparty.upgrade(cluster_name: args[:c], application_name: args[:a], force_variable_definition: args["force-variable-definition"], file_name: args[:f])
46
+ Orchparty.upgrade(cluster_name: args[:c], application_name: args[:a], force_variable_definition: args['force-variable-definition'], file_name: args[:f])
45
47
  end
46
48
  end
47
49
 
48
- desc "Compiles a Orchparty input file to a orchestration framework configuration"
50
+ desc 'Compiles a Orchparty input file to a orchestration framework configuration'
49
51
  command :generate do |com|
50
52
  Orchparty.plugins.each do |name, plugin|
51
- com.desc plugin.desc
52
- com.command(name) do |plugin_command|
53
- plugin_command.flag [:filename,:f,'file-name'], required: true, :desc => 'The Orchparty input file'
54
- plugin_command.flag [:application,:a], required: true, :desc => 'The application that should be compiled'
55
- plugin_command.switch :"force-variable-definition", :default_value => false, :desc => "Raises an Error if the input contains a not defined variable"
56
- plugin.define_flags(plugin_command)
57
- plugin_command.action do |global_options,plugin_options,args|
58
- options = plugin_options.delete(GLI::Command::PARENT)
59
- options[:application] = plugin_options[:application]
60
- options[:filename] = plugin_options[:filename]
61
- options[:force_variable_definition] = plugin_options[:"force-variable-definition"]
62
- Orchparty.generate(name, options, plugin_options)
63
- end
53
+ com.desc plugin.desc
54
+ com.command(name) do |plugin_command|
55
+ plugin_command.flag [:filename, :f, 'file-name'], required: true, desc: 'The Orchparty input file'
56
+ plugin_command.flag %i[application a], required: true, desc: 'The application that should be compiled'
57
+ plugin_command.switch :'force-variable-definition', default_value: false, desc: 'Raises an Error if the input contains a not defined variable'
58
+ plugin.define_flags(plugin_command)
59
+ plugin_command.action do |_global_options, plugin_options, _args|
60
+ options = plugin_options.delete(GLI::Command::PARENT)
61
+ options[:application] = plugin_options[:application]
62
+ options[:filename] = plugin_options[:filename]
63
+ options[:force_variable_definition] = plugin_options[:'force-variable-definition']
64
+ Orchparty.generate(name, options, plugin_options)
64
65
  end
66
+ end
65
67
  end
66
68
  end
67
69
  end
@@ -1,22 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Orchparty
2
- class Context < ::Hashie::Mash
3
- include Hashie::Extensions::DeepMerge
4
- include Hashie::Extensions::DeepMergeConcat
5
- include Hashie::Extensions::MethodAccess
6
- include Hashie::Extensions::Mash::KeepOriginalKeys
4
+ class Context < ::Hashie::Mash
5
+ include Hashie::Extensions::DeepMerge
6
+ include Hashie::Extensions::DeepMergeConcat
7
+ include Hashie::Extensions::MethodAccess
8
+ include Hashie::Extensions::Mash::KeepOriginalKeys
7
9
 
10
+ def method_missing(name, *args)
11
+ raise "#{name} not declared for #{application.name}.#{service.name}" if @_force_variable_definition && !key?(name) && !key?(name.to_s)
8
12
 
9
- def method_missing(name, *args)
10
- raise "#{name} not declared for #{application.name}.#{service.name}" if @_force_variable_definition && !key?(name) && !key?(name.to_s)
11
- super
12
- end
13
+ super
14
+ end
13
15
 
14
- def _force_variable_definition=(v)
15
- @_force_variable_definition = v
16
- end
16
+ attr_writer :_force_variable_definition
17
17
 
18
- def context
19
- self
20
- end
18
+ def context
19
+ self
21
20
  end
21
+ end
22
22
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pathname'
2
4
  module Orchparty
3
5
  class DSLParser
@@ -17,7 +19,7 @@ module Orchparty
17
19
 
18
20
  class Builder
19
21
  def self.build(*args, block)
20
- builder = self.new(*args)
22
+ builder = new(*args)
21
23
  builder.instance_eval(&block)
22
24
  builder._build
23
25
  end
@@ -35,7 +37,6 @@ module Orchparty
35
37
  end
36
38
 
37
39
  class RootBuilder < Builder
38
-
39
40
  def initialize
40
41
  @root = AST.root
41
42
  end
@@ -64,9 +65,8 @@ module Orchparty
64
65
  end
65
66
 
66
67
  class MixinBuilder < Builder
67
-
68
68
  def initialize(name)
69
- @mixin = AST.mixin(name: name)
69
+ @mixin = AST.mixin(name:)
70
70
  end
71
71
 
72
72
  def service(name, &block)
@@ -99,9 +99,8 @@ module Orchparty
99
99
  end
100
100
 
101
101
  class ApplicationBuilder < Builder
102
-
103
102
  def initialize(name)
104
- @application = AST.application(name: name)
103
+ @application = AST.application(name:)
105
104
  end
106
105
 
107
106
  def mix(name)
@@ -143,7 +142,6 @@ module Orchparty
143
142
  end
144
143
 
145
144
  class HashBuilder < Builder
146
-
147
145
  def method_missing(_, *values, &block)
148
146
  if block_given?
149
147
  value = HashBuilder.build(block)
@@ -180,7 +178,6 @@ module Orchparty
180
178
  end
181
179
 
182
180
  class CommonBuilder < Builder
183
-
184
181
  def initialize(node)
185
182
  @node = node
186
183
  end
@@ -191,7 +188,7 @@ module Orchparty
191
188
 
192
189
  def method_missing(name, *values, &block)
193
190
  if block_given?
194
- assign_or_merge(@node, name, HashBuilder.build(block))
191
+ assign_or_merge(@node, name, HashBuilder.build(block))
195
192
  else
196
193
  assign_or_merge(@node, name, values.first)
197
194
  end
@@ -221,9 +218,8 @@ module Orchparty
221
218
  end
222
219
 
223
220
  class ServiceBuilder < CommonBuilder
224
-
225
221
  def initialize(name)
226
- super AST.service(name: name)
222
+ super AST.service(name:)
227
223
  end
228
224
  end
229
225
  end