lono 3.5.0 → 4.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/.gitignore +15 -4
- data/.rspec +1 -0
- data/CHANGELOG.md +15 -1
- data/Gemfile +3 -3
- data/Guardfile +17 -8
- data/{LICENSE → LICENSE.txt} +1 -1
- data/README.md +20 -12
- data/Rakefile +1 -2
- data/{bin → exe}/lono +1 -0
- data/lib/lono.rb +12 -9
- data/lib/lono/cfn.rb +7 -9
- data/lib/lono/cfn/{aws_services.rb → aws_service.rb} +1 -1
- data/lib/lono/cfn/base.rb +41 -38
- data/lib/lono/cfn/create.rb +6 -2
- data/lib/lono/cfn/delete.rb +2 -2
- data/lib/lono/cfn/diff.rb +1 -1
- data/lib/lono/cfn/preview.rb +26 -15
- data/lib/lono/cfn/update.rb +11 -9
- data/lib/lono/cfn/util.rb +3 -3
- data/lib/lono/clean.rb +1 -1
- data/lib/lono/cli.rb +71 -39
- data/lib/lono/command.rb +42 -18
- data/lib/lono/completer.rb +162 -0
- data/lib/lono/completer/script.rb +6 -0
- data/lib/lono/completer/script.sh +10 -0
- data/lib/lono/completion.rb +15 -0
- data/lib/lono/core.rb +23 -9
- data/lib/lono/core/config.rb +20 -0
- data/lib/lono/default/settings.yml +33 -13
- data/lib/lono/help.rb +6 -79
- data/lib/lono/help/cfn.md +6 -0
- data/lib/lono/help/cfn/create.md +22 -0
- data/lib/lono/help/cfn/delete.md +5 -0
- data/lib/lono/help/cfn/diff.md +5 -0
- data/lib/lono/help/cfn/download.md +5 -0
- data/lib/lono/help/cfn/preview.md +11 -0
- data/lib/lono/help/cfn/update.md +21 -0
- data/lib/lono/help/completion.md +22 -0
- data/lib/lono/help/completion_script.md +3 -0
- data/lib/lono/help/generate.md +7 -0
- data/lib/lono/help/hello.md +5 -0
- data/lib/lono/help/import.md +7 -0
- data/lib/lono/help/inspect.md +4 -0
- data/lib/lono/help/inspect/depends.md +3 -0
- data/lib/lono/help/inspect/summary.md +3 -0
- data/lib/lono/help/new.md +8 -0
- data/lib/lono/help/param.md +3 -0
- data/lib/lono/{param/help.rb → help/param/generate.md} +1 -9
- data/lib/lono/help/script/build.md +5 -0
- data/lib/lono/help/script/upload.md +8 -0
- data/lib/lono/help/template.md +4 -0
- data/lib/lono/help/template/bashify.md +4 -0
- data/lib/lono/help/template/generate.md +7 -0
- data/lib/lono/help/user_data.md +3 -0
- data/lib/lono/importer.rb +43 -20
- data/lib/lono/inspector.rb +2 -19
- data/lib/lono/inspector/base.rb +2 -2
- data/lib/lono/inspector/{depends.rb → graph.rb} +3 -3
- data/lib/lono/inspector/summary.rb +1 -1
- data/lib/lono/new.rb +79 -26
- data/lib/lono/new/helper.rb +16 -0
- data/lib/lono/new/message.rb +35 -0
- data/lib/lono/param.rb +1 -2
- data/lib/lono/param/generator.rb +34 -86
- data/lib/lono/project_checker.rb +35 -40
- data/lib/lono/script.rb +19 -0
- data/lib/lono/script/base.rb +9 -0
- data/lib/lono/script/build.rb +73 -0
- data/lib/lono/script/upload.rb +81 -0
- data/lib/lono/sequence.rb +33 -0
- data/lib/lono/setting.rb +83 -0
- data/lib/lono/template.rb +8 -9
- data/lib/lono/template/{aws_services.rb → aws_service.rb} +1 -1
- data/lib/lono/template/context.rb +73 -0
- data/lib/lono/template/dsl.rb +63 -64
- data/lib/lono/template/helper.rb +201 -0
- data/lib/lono/template/template.rb +29 -221
- data/lib/lono/template/upload.rb +41 -33
- data/lib/lono/upgrade4.rb +175 -0
- data/lib/lono/user_data.rb +31 -0
- data/lib/lono/version.rb +1 -1
- data/lib/starter_projects/autoscaling/.gitignore +1 -0
- data/lib/starter_projects/{json_project → autoscaling}/Gemfile +0 -0
- data/lib/starter_projects/{yaml_project → autoscaling}/Guardfile +0 -0
- data/lib/starter_projects/autoscaling/README.md +118 -0
- data/lib/starter_projects/autoscaling/app/definitions/base.rb +2 -0
- data/lib/starter_projects/autoscaling/app/templates/autoscaling.yml +682 -0
- data/lib/starter_projects/autoscaling/config/params/base/autoscaling.txt +6 -0
- data/lib/starter_projects/autoscaling/config/settings.yml +33 -0
- data/lib/starter_projects/ec2/.gitignore +1 -0
- data/lib/starter_projects/{yaml_project → ec2}/Gemfile +0 -0
- data/lib/starter_projects/{json_project → ec2}/Guardfile +1 -1
- data/lib/starter_projects/ec2/README.md +86 -0
- data/lib/starter_projects/ec2/app/definitions/base.rb +2 -0
- data/lib/starter_projects/ec2/app/definitions/development.rb +1 -0
- data/lib/starter_projects/ec2/app/definitions/production.rb +1 -0
- data/lib/starter_projects/{yaml_project → ec2/app}/helpers/my_custom_helper.rb +0 -0
- data/lib/starter_projects/{json_project/templates/user_data/app.sh → ec2/app/partials/user_data/bootstrap.sh} +1 -2
- data/lib/starter_projects/{yaml_project → ec2/app}/templates/example.yml +0 -0
- data/lib/starter_projects/{json_project/params/base/api-web.txt → ec2/config/params/base/example.txt} +0 -0
- data/lib/starter_projects/ec2/config/params/development/example.txt +3 -0
- data/lib/starter_projects/ec2/config/params/production/example.txt +2 -0
- data/lib/starter_projects/ec2/config/settings.yml +33 -0
- data/lib/starter_projects/ec2/config/variables/base.rb +3 -0
- data/lib/starter_projects/ec2/config/variables/development.rb +2 -0
- data/lib/starter_projects/ec2/config/variables/production.rb +2 -0
- data/lib/starter_projects/ec2/welcome.txt +8 -0
- data/lib/starter_projects/skeleton/.gitignore +1 -0
- data/lib/starter_projects/skeleton/Gemfile +3 -0
- data/lib/starter_projects/skeleton/Guardfile +12 -0
- data/lib/starter_projects/skeleton/README.md +53 -0
- data/{spec/fixtures/my_project/templates/.gitkeep → lib/starter_projects/skeleton/app/definitions/base.rb} +0 -0
- data/lib/starter_projects/skeleton/config/settings.yml +33 -0
- data/lib/starter_projects/skeleton/welcome.txt +7 -0
- data/lono.gemspec +12 -10
- data/spec/fixtures/lono_project/.gitignore +1 -0
- data/spec/fixtures/lono_project/Gemfile +3 -0
- data/spec/fixtures/lono_project/Guardfile +12 -0
- data/spec/fixtures/lono_project/app/definitions/base.rb +10 -0
- data/spec/fixtures/lono_project/app/definitions/base/more.rb +7 -0
- data/spec/fixtures/lono_project/app/definitions/development.rb +1 -0
- data/spec/fixtures/lono_project/app/definitions/production.rb +1 -0
- data/spec/fixtures/lono_project/app/helpers/custom_helper.rb +5 -0
- data/spec/fixtures/lono_project/app/partials/security_group.yml +10 -0
- data/{lib/starter_projects/yaml_project/templates/partial → spec/fixtures/lono_project/app/partials}/user_data/bootstrap.sh +8 -2
- data/spec/fixtures/lono_project/app/templates/example.yml +50 -0
- data/{lib/starter_projects/yaml_project/params/base/api-web-prod.txt → spec/fixtures/lono_project/config/params/base/example.txt} +1 -0
- data/spec/fixtures/lono_project/config/params/development/example.txt +1 -0
- data/spec/fixtures/lono_project/config/params/production/example.txt +1 -0
- data/spec/fixtures/lono_project/config/settings.yml +31 -0
- data/spec/fixtures/lono_project/config/variables/base.rb +3 -0
- data/spec/fixtures/lono_project/config/variables/development.rb +1 -0
- data/spec/fixtures/lono_project/config/variables/production.rb +1 -0
- data/spec/fixtures/params/envonly/params/{prod → development}/network.txt +0 -0
- data/spec/fixtures/params/overlay/params/{prod → development}/network.txt +0 -0
- data/spec/fixtures/raw_templates/aws-waf-security-automations.template +2 -2
- data/spec/lib/lono/cfn_spec.rb +6 -9
- data/spec/lib/lono/cli_spec.rb +44 -0
- data/spec/lib/lono/completion_spec.rb +17 -0
- data/spec/lib/lono/inspect_spec.rb +6 -15
- data/spec/lib/lono/param/generator_spec.rb +45 -26
- data/spec/lib/lono/param_spec.rb +1 -3
- data/spec/lib/lono/setting_spec.rb +47 -0
- data/spec/lib/lono/template/dsl_spec.rb +33 -157
- data/spec/lib/lono/template_spec.rb +4 -16
- data/spec/spec_helper.rb +45 -14
- metadata +168 -82
- data/.coveralls.yml +0 -1
- data/lib/lono/cfn/help.rb +0 -103
- data/lib/lono/current_region.rb +0 -42
- data/lib/lono/inspector/help.rb +0 -21
- data/lib/lono/settings.rb +0 -45
- data/lib/lono/template/help.rb +0 -25
- data/lib/lono/template/helpers.rb +0 -136
- data/lib/starter_projects/json_project/.gitignore +0 -1
- data/lib/starter_projects/json_project/config/templates/base/blog.rb +0 -20
- data/lib/starter_projects/json_project/config/templates/base/stacks.rb +0 -58
- data/lib/starter_projects/json_project/templates/db.json +0 -212
- data/lib/starter_projects/json_project/templates/partial/host_record.json +0 -28
- data/lib/starter_projects/json_project/templates/partial/server.json +0 -45
- data/lib/starter_projects/json_project/templates/user_data/db.sh +0 -39
- data/lib/starter_projects/json_project/templates/user_data/db2.sh +0 -2
- data/lib/starter_projects/json_project/templates/user_data/ruby_script.rb +0 -5
- data/lib/starter_projects/json_project/templates/web.json +0 -386
- data/lib/starter_projects/yaml_project/.gitignore +0 -1
- data/lib/starter_projects/yaml_project/config/templates/base/blog.rb +0 -20
- data/lib/starter_projects/yaml_project/config/templates/base/stacks.rb +0 -56
- data/lib/starter_projects/yaml_project/config/templates/prod/stacks.rb +0 -1
- data/lib/starter_projects/yaml_project/config/templates/stag/stacks.rb +0 -1
- data/lib/starter_projects/yaml_project/config/variables/base/variables.rb +0 -4
- data/lib/starter_projects/yaml_project/config/variables/prod/variables.rb +0 -1
- data/lib/starter_projects/yaml_project/config/variables/stag/variables.rb +0 -1
- data/lib/starter_projects/yaml_project/params/base/example.txt +0 -2
- data/lib/starter_projects/yaml_project/params/prod/example.txt +0 -1
- data/lib/starter_projects/yaml_project/params/stag/example.txt +0 -1
- data/lib/starter_projects/yaml_project/templates/db.yml +0 -148
- data/lib/starter_projects/yaml_project/templates/partial/host_record.yml +0 -14
- data/lib/starter_projects/yaml_project/templates/partial/server.yml +0 -59
- data/lib/starter_projects/yaml_project/templates/web.yml +0 -206
- data/spec/fixtures/my_project/config/templates/base/stacks.rb +0 -3
- data/spec/fixtures/my_project/params/my-stack.txt +0 -3
- data/spec/fixtures/my_project/templates/my-stack.yml +0 -0
- data/spec/lib/lono/new_spec.rb +0 -59
- data/spec/lib/lono/template/template_spec.rb +0 -104
- data/spec/lib/lono_spec.rb +0 -27
data/lib/lono/cfn/create.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require "yaml"
|
|
2
|
+
|
|
1
3
|
class Lono::Cfn::Create < Lono::Cfn::Base
|
|
2
4
|
# save_stack is the interface method
|
|
3
5
|
def save_stack(params)
|
|
@@ -23,13 +25,15 @@ class Lono::Cfn::Create < Lono::Cfn::Base
|
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
template_body = IO.read(@template_path)
|
|
26
|
-
|
|
28
|
+
params = {
|
|
27
29
|
stack_name: @stack_name,
|
|
28
30
|
template_body: template_body,
|
|
29
31
|
parameters: params,
|
|
30
32
|
capabilities: capabilities, # ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
|
|
31
33
|
disable_rollback: !@options[:rollback],
|
|
32
|
-
|
|
34
|
+
}
|
|
35
|
+
show_parameters(params, "cfn.create_stack")
|
|
36
|
+
cfn.create_stack(params)
|
|
33
37
|
puts message unless @options[:mute]
|
|
34
38
|
end
|
|
35
39
|
|
data/lib/lono/cfn/delete.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
class Lono::Cfn::Delete
|
|
2
|
-
include Lono::Cfn::
|
|
2
|
+
include Lono::Cfn::AwsService
|
|
3
3
|
include Lono::Cfn::Util
|
|
4
4
|
|
|
5
5
|
def initialize(stack_name, options={})
|
|
@@ -12,7 +12,7 @@ class Lono::Cfn::Delete
|
|
|
12
12
|
if @options[:noop]
|
|
13
13
|
puts "NOOP #{message}"
|
|
14
14
|
else
|
|
15
|
-
are_you_sure?(:delete)
|
|
15
|
+
are_you_sure?(@stack_name, :delete)
|
|
16
16
|
|
|
17
17
|
if stack_exists?(@stack_name)
|
|
18
18
|
cfn.delete_stack(stack_name: @stack_name)
|
data/lib/lono/cfn/diff.rb
CHANGED
data/lib/lono/cfn/preview.rb
CHANGED
|
@@ -20,29 +20,40 @@ class Lono::Cfn::Preview < Lono::Cfn::Base
|
|
|
20
20
|
puts "WARN: Cannot create a change set for the stack because the #{@stack_name} does not exists.".colorize(:yellow)
|
|
21
21
|
return false
|
|
22
22
|
end
|
|
23
|
-
|
|
23
|
+
exit_unless_updatable!(stack_status(@stack_name))
|
|
24
24
|
|
|
25
25
|
template_body = IO.read(@template_path)
|
|
26
|
+
params = {
|
|
27
|
+
change_set_name: change_set_name,
|
|
28
|
+
stack_name: @stack_name,
|
|
29
|
+
template_body: template_body,
|
|
30
|
+
parameters: params,
|
|
31
|
+
capabilities: capabilities, # ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
|
|
32
|
+
}
|
|
33
|
+
show_parameters(params, "cfn.create_change_set")
|
|
26
34
|
begin
|
|
27
|
-
cfn.create_change_set(
|
|
28
|
-
change_set_name: change_set_name,
|
|
29
|
-
stack_name: @stack_name,
|
|
30
|
-
template_body: template_body,
|
|
31
|
-
parameters: params,
|
|
32
|
-
capabilities: capabilities, # ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
|
|
33
|
-
)
|
|
35
|
+
cfn.create_change_set(params)
|
|
34
36
|
rescue Aws::CloudFormation::Errors::ValidationError => e
|
|
35
|
-
|
|
36
|
-
puts "Error creating CloudFormation preview because invalid CloudFormation parameters. Full error message:".colorize(:red)
|
|
37
|
-
puts e.message
|
|
38
|
-
quit(1)
|
|
39
|
-
else
|
|
40
|
-
raise
|
|
41
|
-
end
|
|
37
|
+
handle_error(e)
|
|
42
38
|
end
|
|
43
39
|
true
|
|
44
40
|
end
|
|
45
41
|
|
|
42
|
+
# Example errors:
|
|
43
|
+
# "Template error: variable names in Fn::Sub syntax must contain only alphanumeric characters, underscores, periods, and colons"
|
|
44
|
+
def handle_error(e)
|
|
45
|
+
raise if ENV['FULL_BACKTRACE']
|
|
46
|
+
|
|
47
|
+
if e.message =~ /^Parameters: / || e.message =~ /^Template error: /
|
|
48
|
+
puts "Error creating CloudFormation preview because invalid CloudFormation parameters. Full error message:".colorize(:red)
|
|
49
|
+
puts e.message
|
|
50
|
+
puts "For full backtrace run command again with FULL_BACKTRACE=1"
|
|
51
|
+
quit(1)
|
|
52
|
+
else
|
|
53
|
+
raise
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
46
57
|
def display_change_set
|
|
47
58
|
print "Generating CloudFormation Change Set for preview.."
|
|
48
59
|
change_set = describe_change_set
|
data/lib/lono/cfn/update.rb
CHANGED
|
@@ -16,12 +16,12 @@ class Lono::Cfn::Update < Lono::Cfn::Base
|
|
|
16
16
|
puts "Cannot update a stack because the #{@stack_name} does not exists."
|
|
17
17
|
return
|
|
18
18
|
end
|
|
19
|
-
|
|
19
|
+
exit_unless_updatable!(stack_status(@stack_name))
|
|
20
20
|
|
|
21
21
|
error = nil
|
|
22
22
|
diff.run if @options[:diff]
|
|
23
23
|
preview.run if @options[:preview]
|
|
24
|
-
are_you_sure?(:update)
|
|
24
|
+
are_you_sure?(@stack_name, :update)
|
|
25
25
|
|
|
26
26
|
if @options[:change_set] # defaults to this
|
|
27
27
|
message << " via change set: #{preview.change_set_name}"
|
|
@@ -34,14 +34,16 @@ class Lono::Cfn::Update < Lono::Cfn::Base
|
|
|
34
34
|
|
|
35
35
|
def standard_update(params)
|
|
36
36
|
template_body = IO.read(@template_path)
|
|
37
|
+
params = {
|
|
38
|
+
stack_name: @stack_name,
|
|
39
|
+
template_body: template_body,
|
|
40
|
+
parameters: params,
|
|
41
|
+
capabilities: capabilities, # ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
|
|
42
|
+
disable_rollback: !@options[:rollback],
|
|
43
|
+
}
|
|
44
|
+
show_parameters(params, "cfn.update_stack")
|
|
37
45
|
begin
|
|
38
|
-
cfn.update_stack(
|
|
39
|
-
stack_name: @stack_name,
|
|
40
|
-
template_body: template_body,
|
|
41
|
-
parameters: params,
|
|
42
|
-
capabilities: capabilities, # ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
|
|
43
|
-
disable_rollback: !@options[:rollback],
|
|
44
|
-
)
|
|
46
|
+
cfn.update_stack(params)
|
|
45
47
|
rescue Aws::CloudFormation::Errors::ValidationError => e
|
|
46
48
|
puts "ERROR: #{e.message}".red
|
|
47
49
|
error = true
|
data/lib/lono/cfn/util.rb
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
module Lono::Cfn::Util
|
|
2
|
-
def are_you_sure?(action)
|
|
2
|
+
def are_you_sure?(stack_name, action)
|
|
3
3
|
if @options[:sure]
|
|
4
4
|
sure = 'y'
|
|
5
5
|
else
|
|
6
6
|
message = case action
|
|
7
7
|
when :update
|
|
8
|
-
"Are you sure you want to want to update the stack with the changes? (y/N)"
|
|
8
|
+
"Are you sure you want to want to update the '#{stack_name}' stack with the changes? (y/N)"
|
|
9
9
|
when :delete
|
|
10
|
-
"Are you sure you want to want to delete the stack? (y/N)"
|
|
10
|
+
"Are you sure you want to want to delete the '#{stack_name}' stack? (y/N)"
|
|
11
11
|
end
|
|
12
12
|
puts message
|
|
13
13
|
sure = $stdin.gets
|
data/lib/lono/clean.rb
CHANGED
data/lib/lono/cli.rb
CHANGED
|
@@ -1,63 +1,95 @@
|
|
|
1
|
-
require 'thor'
|
|
2
|
-
require 'lono/command'
|
|
3
|
-
|
|
4
1
|
module Lono
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
desc "import [SOURCE]", "Imports raw CloudFormation template and lono-fies it"
|
|
18
|
-
long_desc Help.import
|
|
19
|
-
option :format, type: :string, default: "yaml", desc: "format for the final template"
|
|
20
|
-
option :casing, default: "underscore", desc: "camelcase or underscore the template name"
|
|
21
|
-
option :name, default: nil, desc: "final name of downloaded template without extension"
|
|
2
|
+
class CLI < Command
|
|
3
|
+
|
|
4
|
+
long_desc Help.text(:new)
|
|
5
|
+
New.cli_options.each do |args|
|
|
6
|
+
option *args
|
|
7
|
+
end
|
|
8
|
+
register(New, "new", "new NAME", "generates new CLI project")
|
|
9
|
+
|
|
10
|
+
desc "import SOURCE", "Imports raw CloudFormation template and lono-fies it"
|
|
11
|
+
long_desc Help.text(:import)
|
|
12
|
+
option :name, required: true, default: nil, desc: "final name of downloaded template without extension"
|
|
13
|
+
option :summary, default: true, type: :boolean, desc: "provide template summary after import"
|
|
22
14
|
def import(source)
|
|
23
15
|
Importer.new(source, options).run
|
|
24
16
|
end
|
|
25
17
|
|
|
26
18
|
desc "generate", "Generate both CloudFormation templates and parameters files"
|
|
27
|
-
Help.generate
|
|
28
|
-
option :clean, type: :boolean,
|
|
29
|
-
option :quiet, type: :boolean,
|
|
30
|
-
option :pretty, type: :boolean, default: true, desc: "json pretty the output. only applies with json format"
|
|
19
|
+
long_desc Help.text(:generate)
|
|
20
|
+
option :clean, type: :boolean, default: true, desc: "remove all output files before generating"
|
|
21
|
+
option :quiet, type: :boolean, desc: "silence the output"
|
|
31
22
|
def generate
|
|
32
|
-
puts "Generating
|
|
33
|
-
|
|
34
|
-
|
|
23
|
+
puts "Generating CloudFormation templates, parameters, and scripts"
|
|
24
|
+
Script::Build.new(options).run
|
|
25
|
+
Template::DSL.new(options).run
|
|
26
|
+
Param::Generator.generate_all(options)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
desc "user_data NAME", "Generates user_data script for debugging"
|
|
30
|
+
long_desc Help.text(:user_data)
|
|
31
|
+
option :clean, type: :boolean, default: true, desc: "remove all output/user_data files before generating"
|
|
32
|
+
def user_data(name)
|
|
33
|
+
Script::Build.new(options).run
|
|
34
|
+
UserData.new(options.merge(name: name)).generate
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
desc "summary STACK", "Prints summary of CloudFormation template"
|
|
38
|
+
long_desc Help.text("summary")
|
|
39
|
+
def summary(name)
|
|
40
|
+
Lono::Inspector::Summary.new(name, options).run
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
desc "xgraph STACK", "Graphs dependencies tree of CloudFormation template resources"
|
|
44
|
+
long_desc Help.text("graph")
|
|
45
|
+
option :display, type: :string, desc: "graph or text", default: "graph"
|
|
46
|
+
option :noop, type: :boolean, desc: "noop mode"
|
|
47
|
+
def xgraph(name)
|
|
48
|
+
Lono::Inspector::Graph.new(name, options).run
|
|
35
49
|
end
|
|
36
50
|
|
|
37
51
|
desc "clean", "Clean up generated files"
|
|
38
52
|
def clean
|
|
39
|
-
|
|
53
|
+
Clean.new(options).run
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
desc "completion *PARAMS", "prints words for auto-completion"
|
|
57
|
+
long_desc Help.text("completion")
|
|
58
|
+
def completion(*params)
|
|
59
|
+
Completer.new(CLI, *params).run
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
desc "completion_script", "generates script that can be eval to setup auto-completion", hide: true
|
|
63
|
+
long_desc Help.text("completion_script")
|
|
64
|
+
def completion_script
|
|
65
|
+
Completer::Script.generate
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
desc "upgrade4", "upgrade from version 3 to 4"
|
|
69
|
+
long_desc Help.text("upgrade3")
|
|
70
|
+
def upgrade4
|
|
71
|
+
Upgrade4.new(options).run
|
|
40
72
|
end
|
|
41
73
|
|
|
42
74
|
desc "version", "Prints version"
|
|
43
75
|
def version
|
|
44
|
-
puts
|
|
76
|
+
puts VERSION
|
|
45
77
|
end
|
|
46
78
|
|
|
47
|
-
desc "template
|
|
48
|
-
long_desc Help.template
|
|
79
|
+
desc "template SUBCOMMAND", "template subcommand tasks"
|
|
80
|
+
long_desc Help.text(:template)
|
|
49
81
|
subcommand "template", Template
|
|
50
82
|
|
|
51
|
-
desc "cfn
|
|
52
|
-
long_desc Help.cfn
|
|
83
|
+
desc "cfn SUBCOMMAND", "cfn subcommand tasks"
|
|
84
|
+
long_desc Help.text(:cfn)
|
|
53
85
|
subcommand "cfn", Cfn
|
|
54
86
|
|
|
55
|
-
desc "param
|
|
56
|
-
long_desc Help.param
|
|
57
|
-
subcommand "param",
|
|
87
|
+
desc "param SUBCOMMAND", "param subcommand tasks"
|
|
88
|
+
long_desc Help.text(:param)
|
|
89
|
+
subcommand "param", Param
|
|
58
90
|
|
|
59
|
-
desc "
|
|
60
|
-
long_desc Help.
|
|
61
|
-
subcommand "
|
|
91
|
+
desc "script SUBCOMMAND", "script subcommand tasks"
|
|
92
|
+
long_desc Help.text(:script)
|
|
93
|
+
subcommand "script", Script
|
|
62
94
|
end
|
|
63
95
|
end
|
data/lib/lono/command.rb
CHANGED
|
@@ -1,23 +1,47 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "thor"
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
3
|
+
# Override thor's long_desc identation behavior
|
|
4
|
+
# https://github.com/erikhuda/thor/issues/398
|
|
5
|
+
class Thor
|
|
6
|
+
module Shell
|
|
7
|
+
class Basic
|
|
8
|
+
def print_wrapped(message, options = {})
|
|
9
|
+
message = "\n#{message}" unless message[0] == "\n"
|
|
10
|
+
stdout.puts message
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
module Lono
|
|
17
|
+
class Command < Thor
|
|
18
|
+
class << self
|
|
19
|
+
def dispatch(m, args, options, config)
|
|
20
|
+
# Allow calling for help via:
|
|
21
|
+
# lono command help
|
|
22
|
+
# lono command -h
|
|
23
|
+
# lono command --help
|
|
24
|
+
# lono command -D
|
|
25
|
+
#
|
|
26
|
+
# as well thor's normal way:
|
|
27
|
+
#
|
|
28
|
+
# lono help command
|
|
29
|
+
help_flags = Thor::HELP_MAPPINGS + ["help"]
|
|
30
|
+
if args.length > 1 && !(args & help_flags).empty?
|
|
31
|
+
args -= help_flags
|
|
32
|
+
args.insert(-2, "help")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# lono version
|
|
36
|
+
# lono --version
|
|
37
|
+
# lono -v
|
|
38
|
+
version_flags = ["--version", "-v"]
|
|
39
|
+
if args.length == 1 && !(args & version_flags).empty?
|
|
40
|
+
args = ["version"]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
super
|
|
19
44
|
end
|
|
20
|
-
super
|
|
21
45
|
end
|
|
22
46
|
end
|
|
23
47
|
end
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Code Explanation:
|
|
3
|
+
|
|
4
|
+
There are 3 types of things to auto-complete:
|
|
5
|
+
|
|
6
|
+
1. command: the command itself
|
|
7
|
+
2. parameters: command parameters.
|
|
8
|
+
3. options: command options
|
|
9
|
+
|
|
10
|
+
Here's an example:
|
|
11
|
+
|
|
12
|
+
mycli hello name --from me
|
|
13
|
+
|
|
14
|
+
* command: hello
|
|
15
|
+
* parameters: name
|
|
16
|
+
* option: --from
|
|
17
|
+
|
|
18
|
+
When command parameters are done processing, the remaining completion words will be options. We can tell that the command params are completed based on the method arity.
|
|
19
|
+
|
|
20
|
+
## Arity
|
|
21
|
+
|
|
22
|
+
For example, say you had a method for a CLI command with the following form:
|
|
23
|
+
|
|
24
|
+
ufo scale service count --cluster development
|
|
25
|
+
|
|
26
|
+
It's equivalent ruby method:
|
|
27
|
+
|
|
28
|
+
scale(service, count) = has an arity of 2
|
|
29
|
+
|
|
30
|
+
So typing:
|
|
31
|
+
|
|
32
|
+
ufo scale service count [TAB] # there are 3 parameters including the "scale" command according to Thor's CLI processing.
|
|
33
|
+
|
|
34
|
+
So the completion should only show options, something like this:
|
|
35
|
+
|
|
36
|
+
--noop --verbose --cluster
|
|
37
|
+
|
|
38
|
+
## Splat Arguments
|
|
39
|
+
|
|
40
|
+
When the ruby method has a splat argument, it's arity is negative. Here are some example methods and their arities.
|
|
41
|
+
|
|
42
|
+
ship(service) = 1
|
|
43
|
+
scale(service, count) = 2
|
|
44
|
+
ships(*services) = -1
|
|
45
|
+
foo(example, *rest) = -2
|
|
46
|
+
|
|
47
|
+
Fortunately, negative and positive arity values are processed the same way. So we take simply take the absolute value of the arity and process it the same.
|
|
48
|
+
|
|
49
|
+
Here are some test cases, hit TAB after typing the command:
|
|
50
|
+
|
|
51
|
+
lono completion
|
|
52
|
+
lono completion hello
|
|
53
|
+
lono completion hello name
|
|
54
|
+
lono completion hello name --
|
|
55
|
+
lono completion hello name --noop
|
|
56
|
+
|
|
57
|
+
lono completion
|
|
58
|
+
lono completion sub:goodbye
|
|
59
|
+
lono completion sub:goodbye name
|
|
60
|
+
|
|
61
|
+
## Subcommands and Thor::Group Registered Commands
|
|
62
|
+
|
|
63
|
+
Sometimes the commands are not simple thor commands but are subcommands or Thor::Group commands. A good specific example is the ufo tool.
|
|
64
|
+
|
|
65
|
+
* regular command: ufo ship
|
|
66
|
+
* subcommand: ufo docker
|
|
67
|
+
* Thor::Group command: ufo init
|
|
68
|
+
|
|
69
|
+
Auto-completion accounts for each of these type of commands.
|
|
70
|
+
=end
|
|
71
|
+
module Lono
|
|
72
|
+
class Completer
|
|
73
|
+
autoload :Script, 'lono/completer/script'
|
|
74
|
+
|
|
75
|
+
def initialize(command_class, *params)
|
|
76
|
+
@params = params
|
|
77
|
+
@current_command = @params[0]
|
|
78
|
+
@command_class = command_class # CLI initiall
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def run
|
|
83
|
+
if subcommand?(@current_command)
|
|
84
|
+
subcommand_class = @command_class.subcommand_classes[@current_command]
|
|
85
|
+
@params.shift # destructive
|
|
86
|
+
Completer.new(subcommand_class, *@params).run # recursively use subcommand
|
|
87
|
+
return
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# full command has been found!
|
|
91
|
+
unless found?(@current_command)
|
|
92
|
+
puts all_commands
|
|
93
|
+
return
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# will only get to here if command aws found (above)
|
|
97
|
+
arity = @command_class.instance_method(@current_command).arity.abs
|
|
98
|
+
if @params.size > arity or thor_group_command?
|
|
99
|
+
puts options_completion
|
|
100
|
+
else
|
|
101
|
+
puts params_completion
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def subcommand?(command)
|
|
106
|
+
@command_class.subcommands.include?(command)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# hacky way to detect that command is a registered Thor::Group command
|
|
110
|
+
def thor_group_command?
|
|
111
|
+
command_params(raw=true) == [[:rest, :args]]
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def found?(command)
|
|
115
|
+
public_methods = @command_class.public_instance_methods(false)
|
|
116
|
+
command && public_methods.include?(command.to_sym)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# all top-level commands
|
|
120
|
+
def all_commands
|
|
121
|
+
commands = @command_class.all_commands.reject do |k,v|
|
|
122
|
+
v.is_a?(Thor::HiddenCommand)
|
|
123
|
+
end
|
|
124
|
+
commands.keys
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def command_params(raw=false)
|
|
128
|
+
params = @command_class.instance_method(@current_command).parameters
|
|
129
|
+
# Example:
|
|
130
|
+
# >> Sub.instance_method(:goodbye).parameters
|
|
131
|
+
# => [[:req, :name]]
|
|
132
|
+
# >>
|
|
133
|
+
raw ? params : params.map!(&:last)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def params_completion
|
|
137
|
+
offset = @params.size - 1
|
|
138
|
+
command_params[offset..-1]
|
|
139
|
+
command_params[offset..-1].first
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def options_completion
|
|
143
|
+
used = ARGV.select { |a| a.include?('--') } # so we can remove used options
|
|
144
|
+
|
|
145
|
+
method_options = @command_class.all_commands[@current_command].options.keys
|
|
146
|
+
class_options = @command_class.class_options.keys
|
|
147
|
+
|
|
148
|
+
all_options = method_options + class_options + ['help']
|
|
149
|
+
|
|
150
|
+
all_options.map! { |o| "--#{o.to_s.gsub('_','-')}" }
|
|
151
|
+
filtered_options = all_options - used
|
|
152
|
+
filtered_options.uniq
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Useful for debugging. Using puts messes up completion.
|
|
156
|
+
def log(msg)
|
|
157
|
+
File.open("/tmp/complete.log", "a") do |file|
|
|
158
|
+
file.puts(msg)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|