lono-pro 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 591e0eaec5e112ef31307c043d0f8228fd1029c6873fa534c8c5b9ae474837f5
4
- data.tar.gz: 85f147681c29bfec81b0c6e68f5e45c37dd3c010de419f8f1d24317d3a3f7d99
3
+ metadata.gz: 81bd2b91f14117ac3b8baec8719b2de27d28b9d82065d5f83ce2cc0513e99a1d
4
+ data.tar.gz: 8b52c80fe8e3a9e6eab4467e59fdce650961637e3df21e60185b5fa30005eb01
5
5
  SHA512:
6
- metadata.gz: 439e966a27599237c2797ef2f55497925af12d726cf35cd623f1cc048e17aadfd904d022886f4f32335ae9ae61f3d39f9259b35150e5c940d8e29d16aa0467a5
7
- data.tar.gz: 066b54869448d2c458acb294fbc3202fd48327e85393a6cdef98cdbbb2e9c128c2623c106a8e20cb12a8ee5ebeaaa7687ba74ea021d054a40d0bfb028b638338
6
+ metadata.gz: 639460ffa51375903e5cb77d6a2f63b7ffbf5a4f69818abf0f1daf1fb1c2392c929030815a4108edeeb37b2b69e5d934ec2a967957b0222c8bf8947d2eaef229
7
+ data.tar.gz: 9c251a223cd25f6023cb0c5add5852d1b86eda9db5e42a9c7176c7afdd44f5d00c4a2b769fc0af256e0b31f03c70d34ced96043a5cd2ac06bb36f684fff3f14b
data/.gitignore CHANGED
@@ -9,3 +9,4 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+ Gemfile.lock
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
5
+
6
+ ## [0.2.0]
7
+ - lono code convert
8
+ - lono code import
9
+
10
+ ## [0.1.0]
11
+ - Initial release
data/Gemfile CHANGED
@@ -1,4 +1,8 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in lono-pro.gemspec
4
3
  gemspec
4
+
5
+ group :development, :test do
6
+ gem "lono"
7
+ # gem "lono", path: "#{ENV['HOME']}/environment/lono"
8
+ end
data/README.md CHANGED
@@ -1,35 +1,35 @@
1
- # Lono::Pro
1
+ # Lono Pro Addon
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/lono/pro`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Lono pro is a paid addon that adds additional features to [lono](https://lono.cloud). Notably, the `lono code import` and `lono code convert` commands.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ The conversion process is not perfect but gets you 80% of the way here. It saves you time.
6
6
 
7
- ## Installation
7
+ ## Usage
8
8
 
9
- Add this line to your application's Gemfile:
9
+ ### lono code convert
10
10
 
11
- ```ruby
12
- gem 'lono-pro'
13
- ```
11
+ The `lono code convert` takes an existing JSON or YAML CloudFormation template and converts it to Ruby code. The Ruby code is printed to standard out.
14
12
 
15
- And then execute:
13
+ ### lono code import
16
14
 
17
- $ bundle
15
+ The `lono code import` converts the template, and also adds it to a generated starter blueprint.
18
16
 
19
- Or install it yourself as:
17
+ ## Installation
20
18
 
21
- $ gem install lono-pro
19
+ Add this line to your lono project's Gemfile:
22
20
 
23
- ## Usage
21
+ ```ruby
22
+ gem "lono-pro"
23
+ ```
24
24
 
25
- TODO: Write usage instructions here
25
+ And then execute:
26
26
 
27
- ## Development
27
+ $ bundle
28
28
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
29
+ You install with the gem command also:
30
30
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
31
+ gem install lono-pro
32
32
 
33
- ## Contributing
33
+ ## API Access
34
34
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/lono-pro.
35
+ Lono Pro uses an API to perform the code conversion. Currently, access to this API service is provided at no cost. In the future, API access will be provided to only [BoltOps Pro](https://www.boltops.com/pro) customers.
@@ -0,0 +1,31 @@
1
+ require "zeitwerk"
2
+
3
+ module Lono
4
+ module Pro
5
+ class Autoloader
6
+ class Inflector < Zeitwerk::Inflector
7
+ def camelize(basename, _abspath)
8
+ map = { cli: "CLI", version: "VERSION" }
9
+ map[basename.to_sym] || super
10
+ end
11
+ end
12
+
13
+ class << self
14
+ def setup
15
+ loader = Zeitwerk::Loader.new
16
+ loader.log! if ENV["LONO_PRO_ZEITWERK_LOG"]
17
+ loader.inflector = Inflector.new
18
+ lib = File.expand_path("../..", __dir__) # lono-pro/lib
19
+ loader.push_dir(lib)
20
+ loader.ignore("#{lib}/lono-pro.rb")
21
+ loader.setup
22
+ loader
23
+ end
24
+
25
+ def require!
26
+ setup.eager_load
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,9 @@
1
+ module Lono::Pro
2
+ module CLI
3
+ Lono::CLI.class_eval do
4
+ desc "code SUBCOMMAND", "code subcommands"
5
+ long_desc Help.text(:code)
6
+ subcommand "code", Code
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,22 @@
1
+ module Lono::Pro
2
+ class Code < Lono::Command
3
+ desc "import SOURCE", "Imports CloudFormation template and converts it to different lono formats."
4
+ long_desc Help.text(:import)
5
+ option :blueprint, default: nil, desc: "final blueprint name"
6
+ option :casing, default: "as-is", desc: "Controls casing of logical ids. IE: as-is, camelcase or underscore"
7
+ option :summary, default: true, type: :boolean, desc: "provide template summary after import"
8
+ option :template, default: nil, desc: "final template name of downloaded template without extension"
9
+ option :template_name_casing, default: "dasherize", desc: "camelcase or dasherize the template name"
10
+ option :type, default: "dsl", desc: "import as a DSL or ERB template"
11
+ def import(source)
12
+ Importer.new(source, options).run
13
+ end
14
+
15
+ desc "convert SOURCE", "Converts snippet of YAML to lono dsl format."
16
+ long_desc Help.text(:convert)
17
+ option :casing, default: "as-is", desc: "Controls casing of logical ids. IE: as-is, camelcase or underscore"
18
+ def convert(source)
19
+ Importer::Converter.new(source, options).run
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ ## Example
2
+
3
+ lono code convert path/to/file
@@ -0,0 +1,3 @@
1
+ ## Example
2
+
3
+ lono code import path/to/file
@@ -0,0 +1,12 @@
1
+ module Lono::Pro
2
+ module Help
3
+ class << self
4
+ # namespaced_command: cfn/create or cfn:create both work.
5
+ def text(namespaced_command)
6
+ path = namespaced_command.to_s.gsub(':','/')
7
+ path = File.expand_path("../help/#{path}.md", __FILE__)
8
+ IO.read(path) if File.exist?(path)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,82 @@
1
+ require "open-uri"
2
+ require "json"
3
+ require "yaml"
4
+
5
+ class Lono::Pro::Importer
6
+ class Base
7
+ def initialize(source, options)
8
+ @source, @options = source, options
9
+ @blueprint = @options[:blueprint] || blueprint_name
10
+ @template = @options[:template] || @blueprint
11
+ Lono::ProjectChecker.check
12
+ # Dont use set_blueprint_root because it doesnt exist yet. We're creating it with import
13
+ Lono.blueprint_root = "#{Lono.root}/blueprints/#{@blueprint}"
14
+
15
+ @tmp_path = "/tmp/lono/import/template.yml"
16
+ end
17
+
18
+ private
19
+ def summarize
20
+ return unless @options[:summary]
21
+ puts "Template Summary:"
22
+ Lono::Inspector::Summary.new(@blueprint, @template, @options).run
23
+ end
24
+
25
+ def create_params(template_path)
26
+ params_path = if @blueprint != @template
27
+ "configs/#{@blueprint}/#{Lono.env}/#{@template}.txt"
28
+ else
29
+ "configs/#{@blueprint}/#{Lono.env}.txt"
30
+ end
31
+ params = Params.new(template_path, params_path)
32
+ params.create
33
+ puts "Params file created at #{pretty_path(params_path)}"
34
+ end
35
+
36
+ # removes the ./ at the beginning if it's there in the path
37
+ def pretty_path(path)
38
+ path.sub("#{Lono.root}/",'')
39
+ end
40
+
41
+ def create_dot_lono(type)
42
+ dot_lono = "#{Lono.blueprint_root}/.lono"
43
+ FileUtils.mkdir_p(dot_lono)
44
+ config = {
45
+ "blueprint_name" => @blueprint,
46
+ "template_type" => "#{type}",
47
+ }
48
+ text = YAML.dump(config)
49
+ IO.write("#{dot_lono}/config.yml", text)
50
+ end
51
+
52
+ def blueprint_name
53
+ return @options[:name] if @options[:name]
54
+ # Else infer name from the original source.
55
+ name = File.basename(@source, ".*")
56
+ @options[:casing] == "camelcase" ? name.camelize : name.underscore.dasherize
57
+ end
58
+
59
+ def download_template(dest_path)
60
+ template = open(@source).read
61
+
62
+ result = if json?(template)
63
+ # abusing YAML.dump(YAML.load()) to convert json to yaml
64
+ YAML.dump(YAML.load(template))
65
+ else
66
+ template # template is already in YAML format
67
+ end
68
+
69
+ folder = File.dirname(dest_path)
70
+ FileUtils.mkdir_p(folder) unless File.exist?(folder)
71
+ IO.write(dest_path, result)
72
+ dest_path
73
+ end
74
+
75
+ def json?(text)
76
+ JSON.load(text)
77
+ true # if reach here than it's just
78
+ rescue JSON::ParserError
79
+ false # not json
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,13 @@
1
+ class Lono::Pro::Importer
2
+ class Converter
3
+ # source is a path
4
+ def initialize(source, options)
5
+ @source, @options = source, options
6
+ end
7
+
8
+ def run
9
+ coder = Service::Coder.new(@source, @options)
10
+ puts coder.translate
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ class Lono::Pro::Importer
2
+ class Dsl < Base
3
+ def run
4
+ tmp_template_path = download_template(@tmp_path)
5
+ translate_to_dsl(tmp_template_path)
6
+ create_dot_lono("dsl")
7
+ create_params(tmp_template_path)
8
+ # Let's not summarize the template in case the Ruby syntax is invalid with the import coder.
9
+ # Add summarize back in later
10
+ # summarize
11
+ end
12
+
13
+ def translate_to_dsl(source_path)
14
+ coder = Service::Coder.new(source_path, @options)
15
+ result = coder.translate
16
+
17
+ path = "#{Lono.config.templates_path}/#{@template}.rb"
18
+ FileUtils.mkdir_p(File.dirname(path))
19
+ IO.write(path, result)
20
+ pretty_path = path.sub("#{Lono.root}/",'')
21
+ puts "Template imported to: #{pretty_path}"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,32 @@
1
+ class Lono::Pro::Importer
2
+ class Erb < Base
3
+ def run
4
+ template_path = "#{Lono.config.templates_path}/#{@template}.yml"
5
+
6
+ puts "=> Imported CloudFormation template.".color(:green)
7
+ download_template(template_path)
8
+ puts "Template downloaded to #{pretty_path(template_path)}"
9
+
10
+ create_dot_lono("erb")
11
+ template_definition_path = add_template_definition
12
+ puts "Template definition added to #{pretty_path(template_definition_path)}"
13
+
14
+ create_params(template_path)
15
+ summarize
16
+ end
17
+
18
+ # Add template definition to app/definitions/base.rb.
19
+ def add_template_definition
20
+ path = "#{Lono.config.definitions_path}/base.rb"
21
+ lines = File.exist?(path) ? IO.readlines(path) : []
22
+ new_template_definition = %Q|template "#{@template}"|
23
+ unless lines.detect { |l| l.include?(new_template_definition) }
24
+ lines << ["\n", new_template_definition]
25
+ result = lines.join('')
26
+ FileUtils.mkdir_p(File.dirname(path))
27
+ IO.write(path, result)
28
+ end
29
+ path
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,52 @@
1
+ class Lono::Pro::Importer
2
+ class Params
3
+ extend Memoist
4
+
5
+ def initialize(template_path, params_path)
6
+ @template_path, @params_path = template_path, params_path
7
+ @params_path = normalize_path(@params_path)
8
+ end
9
+
10
+ # Creates starter params/base/[stack-name].txt file
11
+ def create
12
+ template = YAML.load_file(@template_path)
13
+
14
+ result = []
15
+ required_parameters.each do |name, attributes|
16
+ result << "#{name}="
17
+ end
18
+ optional_parameters.each do |name, attributes|
19
+ key = "#{name}=".ljust(20, ' ')
20
+ result << "##{key} # optional"
21
+ end
22
+ content = result.join("\n") + "\n"
23
+
24
+ folder = File.dirname(@params_path)
25
+ FileUtils.mkdir_p(folder) unless File.exist?(folder)
26
+ IO.write(@params_path, content) unless File.exist?(@params_path)
27
+ end
28
+
29
+ def required_parameters
30
+ parameters.reject { |logical_id, p| p["Default"] }
31
+ end
32
+
33
+ def optional_parameters
34
+ parameters.select { |logical_id, p| p["Default"] }
35
+ end
36
+
37
+ def parameters
38
+ template_data["Parameters"] || []
39
+ end
40
+
41
+ def template_data
42
+ YAML.load(IO.read(@template_path))
43
+ end
44
+ memoize :template_data
45
+
46
+ private
47
+ # Add Lono.root if not already there, helps cli_spec.rb to pass
48
+ def normalize_path(path)
49
+ path.include?(Lono.root.to_s) ? path : "#{Lono.root}/#{path}"
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,64 @@
1
+ require 'base64'
2
+ require 'json'
3
+ require 'net/http'
4
+
5
+ class Lono::Pro::Importer::Service::Coder
6
+ LONO_API = ENV['LONO_API'] || 'https://api.lono.cloud/v1'
7
+
8
+ def initialize(source, options={})
9
+ @source, @options = source, options
10
+ @template = File.exist?(@source) ? IO.read(@source) : @source
11
+ end
12
+
13
+ def translate
14
+ url = "#{LONO_API}/code"
15
+ http = net_http_client(url)
16
+ req = Net::HTTP::Post.new(url) # url includes query string and uri.path does not, must used url
17
+ req = set_request_data(req,
18
+ # Base64 JSON to handle special chars that Rack::LintWrapper cannot process
19
+ template: Base64.encode64(@template),
20
+ lono_version: Lono::VERSION,
21
+ lono_pro_version: Lono::Pro::VERSION,
22
+ lono_command: lono_command,
23
+ )
24
+ res = http.request(req) # send request
25
+
26
+ if res.code == "200"
27
+ data = JSON.load(res.body)
28
+ validity = data["valid_ruby"] ? "valid" : "invalid"
29
+ $stderr.puts <<~EOL
30
+ INFO: The ruby syntax is #{validity}
31
+ Translated ruby code below:
32
+
33
+ EOL
34
+ ruby_code = data["ruby_code"]
35
+ puts ruby_code
36
+ ruby_code
37
+ # TODO: improve error messaging
38
+ else
39
+ puts "Non-successful http response:"
40
+ puts "status code: #{res.code}"
41
+ # puts "headers: #{res.each_header.to_h.inspect}"
42
+ end
43
+ end
44
+
45
+ private
46
+ def net_http_client(url)
47
+ uri = URI(url)
48
+ http = Net::HTTP.new(uri.host, uri.port)
49
+ http.open_timeout = http.read_timeout = 30
50
+ http.use_ssl = true if uri.scheme == 'https'
51
+ http
52
+ end
53
+
54
+ def set_request_data(req, data)
55
+ text = JSON.dump(data)
56
+ req.body = text
57
+ req.content_length = text.bytesize
58
+ req
59
+ end
60
+
61
+ def lono_command
62
+ "lono #{ARGV.join(' ')}"
63
+ end
64
+ end
@@ -0,0 +1,21 @@
1
+ module Lono::Pro
2
+ class Importer
3
+ def initialize(source, options)
4
+ @source, @options = source, options
5
+
6
+ Lono::ProjectChecker.check
7
+ # Dont use set_blueprint_root because it doesnt exist yet. The import creates it
8
+ Lono.blueprint_root = "#{Lono.root}/blueprints/#{@blueprint}"
9
+ end
10
+
11
+ def run
12
+ # Examples:
13
+ # Lono::Pro::Importer::Erb.new(source, options.clone).run
14
+ # Lono::Pro::Importer::Dsl.new(source, options.clone).run
15
+ type = @options[:type] || 'dsl'
16
+ importer_class = "Lono::Pro::Importer::#{type.classify}"
17
+ importer_class = Object.const_get(importer_class)
18
+ importer_class.new(@source, @options.clone).run
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,5 @@
1
1
  module Lono
2
2
  module Pro
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
data/lib/lono/pro.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  require "lono/pro/version"
2
+ require "lono/pro/autoloader"
3
+ Lono::Pro::Autoloader.require!
2
4
 
3
5
  module Lono
4
6
  module Pro
5
- class Error < StandardError; end
6
- # Your code goes here...
7
7
  end
8
- end
8
+ end
data/lib/lono-pro.rb ADDED
@@ -0,0 +1 @@
1
+ require_relative "lono/pro"
data/lono-pro.gemspec CHANGED
@@ -6,9 +6,9 @@ Gem::Specification.new do |spec|
6
6
  spec.name = "lono-pro"
7
7
  spec.version = Lono::Pro::VERSION
8
8
  spec.authors = ["Tung Nguyen"]
9
- spec.email = ["tongueroo@gmail.com"]
9
+ spec.email = ["tung@boltops.com"]
10
10
 
11
- spec.summary = %q{Lono Pro Addon}
11
+ spec.summary = "Lono Pro Addon"
12
12
  spec.homepage = "https://github.com/tongueroo/lono-pro"
13
13
  spec.license = "https://www.boltops.com/boltops-community-license"
14
14
 
@@ -25,6 +25,8 @@ Gem::Specification.new do |spec|
25
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
26
  spec.require_paths = ["lib"]
27
27
 
28
+ spec.add_dependency "zeitwerk"
29
+
28
30
  spec.add_development_dependency "bundler", "~> 2.0"
29
31
  spec.add_development_dependency "rake", "~> 10.0"
30
32
  spec.add_development_dependency "rspec", "~> 3.0"
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lono-pro
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-05 00:00:00.000000000 Z
11
+ date: 2019-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: zeitwerk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -54,7 +68,7 @@ dependencies:
54
68
  version: '3.0'
55
69
  description:
56
70
  email:
57
- - tongueroo@gmail.com
71
+ - tung@boltops.com
58
72
  executables: []
59
73
  extensions: []
60
74
  extra_rdoc_files: []
@@ -62,13 +76,26 @@ files:
62
76
  - ".gitignore"
63
77
  - ".rspec"
64
78
  - ".travis.yml"
79
+ - CHANGELOG.md
65
80
  - Gemfile
66
81
  - LICENSE.txt
67
82
  - README.md
68
83
  - Rakefile
69
- - bin/console
70
- - bin/setup
84
+ - lib/lono-pro.rb
71
85
  - lib/lono/pro.rb
86
+ - lib/lono/pro/autoloader.rb
87
+ - lib/lono/pro/cli.rb
88
+ - lib/lono/pro/code.rb
89
+ - lib/lono/pro/help.rb
90
+ - lib/lono/pro/help/convert.md
91
+ - lib/lono/pro/help/import.md
92
+ - lib/lono/pro/importer.rb
93
+ - lib/lono/pro/importer/base.rb
94
+ - lib/lono/pro/importer/converter.rb
95
+ - lib/lono/pro/importer/dsl.rb
96
+ - lib/lono/pro/importer/erb.rb
97
+ - lib/lono/pro/importer/params.rb
98
+ - lib/lono/pro/importer/service/coder.rb
72
99
  - lib/lono/pro/version.rb
73
100
  - lono-pro.gemspec
74
101
  homepage: https://github.com/tongueroo/lono-pro
data/bin/console DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "lono/pro"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here